Opérateur de décalage vers la droite non signé
Remarque
Cet article est une spécification de fonctionnalité. La spécification sert de document de conception pour la fonctionnalité. Elle inclut les changements de spécification proposés, ainsi que les informations nécessaires à la conception et au développement de la fonctionnalité. Ces articles sont publiés jusqu'à ce que les changements proposés soient finalisés et incorporés dans la spécification ECMA actuelle.
Il peut y avoir des différences entre la spécification de la fonctionnalité et l'implémentation réalisée. Ces différences sont consignées dans les notes pertinentes de la réunion de conception linguistique (LDM).
Pour en savoir plus sur le processus d'adoption des speclets de fonctionnalité dans la norme du langage C#, consultez l'article sur les spécifications.
Problème de champion : https://github.com/dotnet/csharplang/issues/4682
Récapitulatif
C# prendra en charge un opérateur de décalage à droite non signé en tant qu’opérateur natif (pour les types intégraux primitifs) et en tant qu’opérateur défini par l’utilisateur.
Motivation
Lorsque l'on travaille avec une valeur intégrale signée, il n'est pas rare que l'on doive décaler des bits vers la droite sans reproduire le bit de poids fort à chaque décalage. Bien que cela puisse être obtenu pour les types intégraux primitifs avec un opérateur de décalage standard, il est nécessaire de faire une conversion en un type non signé avant l’opération de décalage et une conversion inverse après. Dans le contexte des interfaces mathématiques génériques que les bibliothèques prévoient d'exposer, cela est potentiellement plus problématique car le type peut ne pas avoir une contrepartie non signée définie ou connue d'emblée par le code mathématique générique, alors qu'un algorithme peut s'appuyer sur la capacité à effectuer une opération de décalage vers la droite non signée.
Conception détaillée
Opérateurs et signes de ponctuation
La section 6.4.6 sera modifiée pour inclure l'opérateur >>>
- l'opérateur de décalage à droite non signé :
unsigned_right_shift
: '>>>'
;
unsigned_right_shift_assignment
: '>>>='
;
Aucun caractère d'aucune sorte (pas même les espaces blancs) n'est autorisé entre les jetons des productions unsigned_right_shift et unsigned_right_shift_assignment. Ces productions font l'objet d'un traitement spécial afin de permettre la gestion correcte des listes de type_parameter_lists
Opérateurs de décalage
La section 12.11 sera modifiée pour inclure l'opérateur >>>
- l'opérateur de décalage à droite non signé :
Les opérateurs <<
, >>
et >>>
sont utilisés pour réaliser des opérations de décalage de bits.
shift_expression
: additive_expression
| shift_expression '<<' additive_expression
| shift_expression right_shift additive_expression
| shift_expression unsigned_right_shift additive_expression
;
Pour une opération de la forme x << count
, x >> count
ou x >>> count
la résolution de surcharge de l’opérateur binaire (§12.4.5) est appliquée pour sélectionner une implémentation spécifique de l’opérateur. Les opérandes sont convertis en types de paramètre de l’opérateur sélectionné, et le type du résultat correspond au type de retour de l’opérateur.
Les opérateurs de décalage non signés prédéfinis prendront en charge le même ensemble de signatures que les opérateurs de décalage signés prédéfinis dans l'implémentation actuelle.
Décalage vers la droite :
int operator >>>(int x, int count); uint operator >>>(uint x, int count); long operator >>>(long x, int count); ulong operator >>>(ulong x, int count); nint operator >>>(nint x, int count); nuint operator >>>(nuint x, int count);
L’opérateur
>>>
déplacex
vers la droite d’un nombre de bits calculé comme décrit ci-dessous.Les bits de faible ordre de
x
sont ignorés, les bits restants sont décalés vers la droite et les positions de bits vides de l’ordre élevé sont définies sur zéro.
Pour les opérateurs prédéfinis, le nombre de bits à décaler est calculé comme suit:
- Lorsque le type de
x
estint
ouuint
, le nombre de décalages est donné par les cinq bits de bas ordre decount
. En d'autres termes, le nombre de décalages est calculé à partir decount & 0x1F
. - Lorsque le type de
x
estlong
ouulong
, le nombre de décalages est donné par les six bits de poids faible decount
. En d'autres termes, le nombre de décalages est calculé à partir decount & 0x3F
.
Si le nombre de décalages résultant est nul, les opérateurs de décalage renvoient simplement la valeur de x
.
Les opérations de décalage ne provoquent jamais de dépassements de capacité et donnent les mêmes résultats dans des contextes checked
et unchecked
.
Opérateurs d’assignation
La section 12.21 sera modifiée pour inclure unsigned_right_shift_assignment comme suit :
assignment_operator
: '='
| '+='
| '-='
| '*='
| '/='
| '%='
| '&='
| '|='
| '^='
| '<<='
| right_shift_assignment
| unsigned_right_shift_assignment
;
Types intégraux
Les types intégraux de la section §8.3.6 seront ajustés pour inclure des informations sur l’opérateur >>>
. Le point pertinent est le suivant :
- Pour les opérateurs binaires
<<
,>>
et>>>
, l’opérande gauche est converti en typeT
, oùT
est le premier deint
,uint
,long
etulong
, qui peuvent représenter entièrement toutes les valeurs possibles de l’opérande. L’opération est ensuite effectuée à l’aide de la précision du typeT
, et le type du résultat estT
.
Expressions de constantes
L’opérateur >>>
sera ajouté à l’ensemble de constructions autorisées dans les expressions constantes au §12.23.
Surcharge d’opérateur
L’opérateur >>>
sera ajouté à l’ensemble d’opérateurs binaires surchargeables au §12.4.3.
Opérateurs levés
L’opérateur >>>
sera ajouté à l’ensemble d’opérateurs binaires autorisant une forme élevée au §12.4.8.
Priorité des opérateurs et associativité
La section §12.4.2 sera ajustée pour ajouter les opérateurs >>>
à la catégorie « Shift » et >>>=
à la catégorie « Affectation et l'expression lambda ».
Ambiguïtés grammaticales
L’opérateur >>>
est soumis aux mêmes ambiguïtés grammaticales décrites au §6.2.5 comme opérateur de >>
standard.
Opérateurs
La section §15.10 sera ajustée pour inclure l'opérateur >>>
.
overloadable_binary_operator
: '+' | '-' | '*' | '/' | '%' | '&' | '|' | '^' | '<<'
| right_shift | unsigned_right_shift | '==' | '!=' | '>' | '<' | '>=' | '<='
;
Opérateurs binaires
La signature d’un opérateur >>>
est soumise aux mêmes règles qu’au §15.10.3 pour la signature d’un opérateur >>
.
Nom des métadonnées
La section « I.10.3.2 Binary operators » de l'ECMA-335 a déjà réservé le nom d'un opérateur de décalage à droite non signé - op_UnsignedRightShift.
Arbres d'expression Linq
L'opérateur >>>
ne sera pas pris en charge dans les arbres d'expressions LINQ, car la sémantique des opérateurs >>>
prédéfinis sur les types signés ne peut pas être représentée avec précision sans ajouter de conversions à un type non signé et inversement. Consultez la rubrique https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator (éventuellement en anglais) pour plus d'informations.
Liaison dynamique
Il semble que la liaison dynamique utilise les valeurs de l'enum System.Linq.Expressions.ExpressionType pour communiquer le type d'opérateur binaire à la liaison d'exécution. Comme nous n'avons pas de membre représentant spécifiquement l'opérateur unsigned right shift, la liaison dynamique pour l'opérateur >>>
ne sera pas supportée et la section sur la liaison statique et dynamique (12.3) sera ajustée pour refléter cela.
Inconvénients
Alternatives
Arbres d'expression Linq
L'opérateur >>>
sera pris en charge dans les arbres d'expression Linq.
- Pour un opérateur défini par l’utilisateur, un nœud BinaryExpression pointant vers la méthode d’opérateur est créé.
- Pour les opérateurs prédéfinis
- lorsque le premier opérande est un type non signé, un nœud BinaryExpression est créé.
- lorsque le premier opérande est un type signé, une conversion du premier opérande en type non signé est ajoutée, un nœud BinaryExpression est créé et la conversion du résultat vers le type signé est ajoutée.
Exemple :
Expression<System.Func<int, int, int>> z = (x, y) => x >>> y; // (x, y) => Convert((Convert(x, UInt32) >> y), Int32)
Resolution:
En cas de rejet, consultez la rubrique https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md#unsigned-right-shift-operator pour plus d'informations.
Questions non résolues
Réunions de conception
https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-02-09.md
C# feature specifications