Opérateurs au niveau du bit et opérateurs de décalage (référence C#)
Les opérateurs au niveau du bit et de décalage incluent le complément de bits unaire, les décalages binaires vers la gauche et la droite, le décalage vers la droite non signé, et les opérateurs logiques binaires AND, OR et OR exclusif. Ces opérandes prennent des opérandes des types numériques intégraux ou du type char.
- Opérateur unaire
~
(complément de bits) - Opérateurs binaires
<<
(décalage vers la gauche),>>
(décalage vers la droite) et>>>
(décalage vers la droite non signé) - Opérateurs binaires
&
(AND logique),|
(OR logique) et^
(OR exclusif logique)
Ces opérateurs sont définis pour les types int
, uint
, long
et ulong
. Lorsque les deux opérandes sont d’autres types intégraux (sbyte
, byte
, short
, ushort
ou char
), leurs valeurs sont converties en valeurs de type int
, qui est également le type de résultat d’une opération. Lorsque les opérandes sont de différents types intégraux, leurs valeurs sont converties vers le type intégral le plus proche. Pour plus d’informations, consultez la section Promotions numériques de la spécification du langage C#. Les opérateurs composés (tels que >>=
) ne convertissent pas leurs arguments en int
et n’ont pas le type de résultat int
.
Les opérateurs &
, |
et ^
sont également définis pour les opérandes du type bool
. Pour plus d’informations, consultez Opérateurs logiques booléens.
Les opérations de décalage et au niveau du bit ne provoquent jamais de dépassements de capacité et donnent les mêmes résultats dans des contextes checked et unchecked.
Opérateur de complément de bits ~
L’opérateur ~
produit un complément de bits de son opérande en inversant chaque bit :
uint a = 0b_0000_1111_0000_1111_0000_1111_0000_1100;
uint b = ~a;
Console.WriteLine(Convert.ToString(b, toBase: 2));
// Output:
// 11110000111100001111000011110011
Vous pouvez également utiliser le symbole ~
pour déclarer des finaliseurs. Pour plus d’informations, consultez Finaliseurs.
Opérateur de décalage gauche <<
L’opérateur <<
décale son opérande de partie gauche vers le nombre de bits spécifié par son opérande de partie droite. Pour obtenir des informations sur la façon dont l’opérande droit définit la valeur de décalage, consultez la section Valeur de décalage des opérateurs de décalage.
L’opération de décalage gauche supprime les bits d’ordre supérieur qui sont en dehors de la plage du type de résultat, et définit les positions de bits vides d’ordre inférieur sur zéro, comme le montre l’exemple suivant :
uint x = 0b_1100_1001_0000_0000_0000_0000_0001_0001;
Console.WriteLine($"Before: {Convert.ToString(x, toBase: 2)}");
uint y = x << 4;
Console.WriteLine($"After: {Convert.ToString(y, toBase: 2)}");
// Output:
// Before: 11001001000000000000000000010001
// After: 10010000000000000000000100010000
Étant donné que les opérateurs de décalage sont définis uniquement pour les types int
, uint
, long
et ulong
, le résultat d’une opération contient toujours au moins 32 bits. Si l’opérande de partie gauche est d’un autre type intégral (sbyte
, byte
, short
, ushort
ou char
), sa valeur est convertie en type int
, comme l’indique l’exemple suivant :
byte a = 0b_1111_0001;
var b = a << 8;
Console.WriteLine(b.GetType());
Console.WriteLine($"Shifted byte: {Convert.ToString(b, toBase: 2)}");
// Output:
// System.Int32
// Shifted byte: 1111000100000000
Opérateur de décalage vers la droite >>
L’opérateur >>
décale son opérande de partie gauche vers le nombre de bits défini par son opérande de partie droite. Pour obtenir des informations sur la façon dont l’opérande droit définit la valeur de décalage, consultez la section Valeur de décalage des opérateurs de décalage.
L’opération de décalage vers la droite ignore les bits d’ordre inférieur, comme le montre l’exemple suivant :
uint x = 0b_1001;
Console.WriteLine($"Before: {Convert.ToString(x, toBase: 2), 4}");
uint y = x >> 2;
Console.WriteLine($"After: {Convert.ToString(y, toBase: 2).PadLeft(4, '0'), 4}");
// Output:
// Before: 1001
// After: 0010
Les positions de bits vides d’ordre supérieur sont définies en fonction du type de l’opérande de partie gauche comme suit :
Si l’opérande gauche est de type
int
oulong
, l’opérateur de décalage vers la droite effectue un décalage arithmétique : la valeur du bit le plus significatif (le bit de signe) de l’opérande gauche est propagée vers les positions des bits vides de poids fort. Autrement dit, les positions de bits vides d’ordre supérieur sont définies sur zéro si l’opérande de partir gauche n’est pas négatif et sur un s’il est négatif.int a = int.MinValue; Console.WriteLine($"Before: {Convert.ToString(a, toBase: 2)}"); int b = a >> 3; Console.WriteLine($"After: {Convert.ToString(b, toBase: 2)}"); // Output: // Before: 10000000000000000000000000000000 // After: 11110000000000000000000000000000
Si l’opérande gauche est de type
uint
ouulong
, l’opérateur de décalage vers la droite effectue un décalage logique : les positions des bits vides de poids fort sont toujours définies sur zéro.uint c = 0b_1000_0000_0000_0000_0000_0000_0000_0000; Console.WriteLine($"Before: {Convert.ToString(c, toBase: 2), 32}"); uint d = c >> 3; Console.WriteLine($"After: {Convert.ToString(d, toBase: 2).PadLeft(32, '0'), 32}"); // Output: // Before: 10000000000000000000000000000000 // After: 00010000000000000000000000000000
Notes
Utilisez l’opérateur de décalage vers la droite non signé pour effectuer un décalage logique sur les opérandes de types entiers signés. Cela est préférable au cast d’un opérande gauche en type non signé, puis au cast du résultat d’une opération de décalage en type signé.
Opérateur de décalage vers la droite non signé >>>
Disponible en C# 11 et versions ultérieures, l’opérateur >>>
décale son opérande gauche vers la droite du nombre de bits défini par son opérande droit. Pour obtenir des informations sur la façon dont l’opérande droit définit la valeur de décalage, consultez la section Valeur de décalage des opérateurs de décalage.
L’opérateur >>>
effectue toujours un décalage logique. Autrement dit, les positions de bits vides de poids fort sont toujours définies sur zéro, quel que soit le type de l’opérande gauche. L’opérateur >>
effectue un décalage arithmétique (autrement dit, la valeur du bit le plus significatif est propagée aux positions de bits vides de poids fort) si l’opérande gauche est d’un type signé. L’exemple suivant illustre la différence entre les opérateurs >>
et >>>
pour un opérande gauche négatif :
int x = -8;
Console.WriteLine($"Before: {x,11}, hex: {x,8:x}, binary: {Convert.ToString(x, toBase: 2), 32}");
int y = x >> 2;
Console.WriteLine($"After >>: {y,11}, hex: {y,8:x}, binary: {Convert.ToString(y, toBase: 2), 32}");
int z = x >>> 2;
Console.WriteLine($"After >>>: {z,11}, hex: {z,8:x}, binary: {Convert.ToString(z, toBase: 2).PadLeft(32, '0'), 32}");
// Output:
// Before: -8, hex: fffffff8, binary: 11111111111111111111111111111000
// After >>: -2, hex: fffffffe, binary: 11111111111111111111111111111110
// After >>>: 1073741822, hex: 3ffffffe, binary: 00111111111111111111111111111110
Opérateur AND logique &
L’opérateur &
calcule le AND logique au niveau du bit de ses opérandes intégraux :
uint a = 0b_1111_1000;
uint b = 0b_1001_1101;
uint c = a & b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 10011000
Pour les opérandes bool
, l’opérateur &
calcule le AND logique de ses opérandes. L’opérateur unaire &
est l’opérateur address-of.
L’opérateur OR exclusif logique ^
L’opérateur ^
calcule le OR exclusif logique au niveau du bit, également appelé XOR logique au niveau du bit, de ses opérandes intégraux :
uint a = 0b_1111_1000;
uint b = 0b_0001_1100;
uint c = a ^ b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 11100100
Pour les opérandes bool
, l’opérateur ^
calcule le OR exclusif logique de ses opérandes.
L’opérateur OU logique |
L’opérateur |
calcule le OR logique au niveau du bit de ses opérandes intégraux :
uint a = 0b_1010_0000;
uint b = 0b_1001_0001;
uint c = a | b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 10110001
Pour les opérandes bool
, l’opérateur |
calcule le OR logique de ses opérandes.
Assignation composée
Pour un opérateur binaire op
, une expression d’assignation composée du formulaire
x op= y
équivaut à :
x = x op y
sauf que x
n’est évalué qu’une seule fois.
L’exemple suivant montre l’utilisation de l’assignation composée avec des opérateurs de décalage et des opérateurs au niveau du bit :
uint INITIAL_VALUE = 0b_1111_1000;
uint a = INITIAL_VALUE;
a &= 0b_1001_1101;
Display(a); // output: 10011000
a = INITIAL_VALUE;
a |= 0b_0011_0001;
Display(a); // output: 11111001
a = INITIAL_VALUE;
a ^= 0b_1000_0000;
Display(a); // output: 01111000
a = INITIAL_VALUE;
a <<= 2;
Display(a); // output: 1111100000
a = INITIAL_VALUE;
a >>= 4;
Display(a); // output: 00001111
a = INITIAL_VALUE;
a >>>= 4;
Display(a); // output: 00001111
void Display(uint x) => Console.WriteLine($"{Convert.ToString(x, toBase: 2).PadLeft(8, '0'), 8}");
En raison des promotions numériques, le résultat de l’opération op
risque de ne pas être implicitement convertible en type T
de x
. Dans ce cas, si op
est un opérateur prédéfini et que le résultat de l’opération est explicitement convertible en type T
de x
, une expression d’assignation composée de la forme x op= y
équivaut à x = (T)(x op y)
, sauf que x
n’est évalué qu’une seule fois. L’exemple suivant illustre ce comportement :
byte x = 0b_1111_0001;
int b = x << 8;
Console.WriteLine($"{Convert.ToString(b, toBase: 2)}"); // output: 1111000100000000
x <<= 8;
Console.WriteLine(x); // output: 0
Priorité des opérateurs
La liste suivante présente les opérateurs au niveau du bit et les opérateurs de décalage par ordre de précédence, de la plus élevée à la plus basse :
- Opérateur de complément de bits
~
- Opérateurs de décalage
<<
,>>
et>>>
- L’opérateur AND logique
&
- Opérateur OR exclusif logique
^
- Opérateur OR logique
|
Utilisez des parenthèses, ()
, pour modifier l’ordre d’évaluation imposé par la précédence des opérateurs :
uint a = 0b_1101;
uint b = 0b_1001;
uint c = 0b_1010;
uint d1 = a | b & c;
Display(d1); // output: 1101
uint d2 = (a | b) & c;
Display(d2); // output: 1000
void Display(uint x) => Console.WriteLine($"{Convert.ToString(x, toBase: 2), 4}");
Pour obtenir la liste complète des opérateurs C# classés par niveau de priorité, consultez la section Priorité des opérateurs de l’article Opérateurs C#.
Valeur de décalage des opérateurs de décalage
Pour les expressions x << count
, x >> count
et x >>> count
, la valeur de décalage réelle dépend du type de x
, comme suit :
Si le type de
x
estint
ouuint
, la valeur de décalage est définie par les cinq bits de poids faible de l’opérande droit. La valeur de décalage est donc calculée à partir decount & 0x1F
(ou decount & 0b_1_1111
).Si le type de
x
estlong
ouulong
, la valeur de décalage est définie par les six bits de poids faible de l’opérande droit. La valeur de décalage est donc calculée à partir decount & 0x3F
(ou decount & 0b_11_1111
).
L’exemple suivant illustre ce comportement :
int count1 = 0b_0000_0001;
int count2 = 0b_1110_0001;
int a = 0b_0001;
Console.WriteLine($"{a} << {count1} is {a << count1}; {a} << {count2} is {a << count2}");
// Output:
// 1 << 1 is 2; 1 << 225 is 2
int b = 0b_0100;
Console.WriteLine($"{b} >> {count1} is {b >> count1}; {b} >> {count2} is {b >> count2}");
// Output:
// 4 >> 1 is 2; 4 >> 225 is 2
int count = -31;
int c = 0b_0001;
Console.WriteLine($"{c} << {count} is {c << count}");
// Output:
// 1 << -31 is 2
Notes
Comme le montre l’exemple précédent, le résultat d’une opération de décalage peut être différent de zéro, même si la valeur de l’opérande droit est supérieure au nombre de bits dans l’opérande gauche.
Opérateurs logiques d’énumération
Les opérateurs ~
, &
, |
et ^
sont également pris en charge par tout type d’énumération. Pour les opérandes du même type énumération, une opération logique est effectuée sur les valeurs correspondantes du type intégral sous-jacent. Par exemple, pour tout x
et y
d’un type énumération T
avec un type sous-jacent U
, l’expression x & y
produit le même résultat que l’expression (T)((U)x & (U)y)
.
Vous utilisez généralement des opérateurs logiques au niveau du bit avec un type énumération qui est défini à l’aide de l’attribut Flags. Pour plus d’informations, consultez la section Types énumération comme indicateurs binaires de l’articleTypes énumération.
Capacité de surcharge de l’opérateur
Un type défini par l’utilisateur peut surcharger les opérateurs ~
, <<
, >>
, >>>
, &
, |
et ^
. Quand un opérateur binaire est surchargé, l’opérateur d’assignation composée correspondant est aussi implicitement surchargé. Un type défini par l’utilisateur ne peut pas surcharger explicitement un opérateur d’assignation composée.
Si un type défini par l’utilisateur T
surcharge l’opérateur <<
, >>
ou >>>
, le type de l’opérande gauche doit être T
. En C# 10 et versions antérieures, le type de l’opérande droit doit être int
. Depuis C# 11, l’opérande droit d’un opérateur de décalage surchargé peut être d’un type quelconque.
spécification du langage C#
Pour plus d’informations, consultez les sections suivantes de la spécification du langage C# :
- Opérateur de complément de bits
- Opérateurs de décalage
- Opérateurs logiques
- Assignation composée
- Promotions numériques
- C# 11 – Exigences de décalage assouplies
- C# 11 – Opérateur logique de décalage vers la droite