Bitwise- en shiftoperators (C#-verwijzing)
De bitsgewijze operatoren en shifts bevatten een ongewijze aanvulling op bitgewijze aanvulling, binaire shift naar links en rechts, niet-ondertekende rechter shift, en de binaire logische AND, OR en exclusieve OR-operators. Deze operanden nemen operanden van de integrale numerieke typen of het tekentype .
- Unaire
~
operator (bitwise complement) - Binaire
<<
operatoren (linker shift),>>
(rechter shift) en>>>
(niet-ondertekende rechter shift) - Binaire operatoren (logische EN),
|
(logische OF)- en^
(logische exclusieve OR)-operators&
Deze operatoren worden gedefinieerd voor de int
typen , uint
en ulong
long
typen. Wanneer beide operanden van andere integrale typen zijn (sbyte
, byte
, short
, ushort
of char
), worden de waarden geconverteerd naar het int
type, wat ook het resultaattype van een bewerking is. Wanneer operanden van verschillende integrale typen zijn, worden hun waarden geconverteerd naar het dichtstbijzijnde integrale type. Zie de sectie Numerieke promoties van de C#-taalspecificatie voor meer informatie. De samengestelde operators (zoals >>=
) converteren hun argumenten niet naar int
of hebben het resultaattype als int
.
De &
operatoren , |
en ^
operatoren worden ook gedefinieerd voor operanden van het bool
type. Zie Booleaanse logische operators voor meer informatie.
Bitwise en shift-bewerkingen veroorzaken nooit overloop en produceren dezelfde resultaten in gecontroleerde en niet-gecontroleerde contexten.
Bitsgewijze complementoperator ~
De ~
operator produceert een bitsgewijze aanvulling van de operand door elke bit om te draaien:
uint a = 0b_0000_1111_0000_1111_0000_1111_0000_1100;
uint b = ~a;
Console.WriteLine(Convert.ToString(b, toBase: 2));
// Output:
// 11110000111100001111000011110011
U kunt ook het ~
symbool gebruiken om finalizers te declareren. Zie Finalizers voor meer informatie.
Operator voor linkerdienst <<
De <<
operator verschuift de linkeroperand naar links door het aantal bits dat is gedefinieerd door de rechteroperand. Zie het aantal diensten van de sectie Shift-operatoren voor informatie over hoe de rechteroperand het aantal diensten definieert.
Met de bewerking links verplaatsen worden de bits met hoge volgorde verwijderd die buiten het bereik van het resultaattype vallen en worden de lege bitposities met lage volgorde ingesteld op nul, zoals in het volgende voorbeeld wordt weergegeven:
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
Omdat de shiftoperators alleen zijn gedefinieerd voor de int
typenlong
uint
ulong
, bevat het resultaat van een bewerking altijd ten minste 32 bits. Als de linkeroperand van een ander integraal type (sbyte
, byte
, ushort
short
ofchar
) is, wordt de waarde ervan geconverteerd naar het int
type, zoals in het volgende voorbeeld wordt weergegeven:
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
Operator voor rechter shift >>
De >>
operator verschuift de linkeroperand naar rechts door het aantal bits dat is gedefinieerd door de rechteroperand. Zie het aantal diensten van de sectie Shift-operatoren voor informatie over hoe de rechteroperand het aantal diensten definieert.
Met de right-shift-bewerking worden de bits met lage volgorde verwijderd, zoals in het volgende voorbeeld wordt weergegeven:
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
De lege bitposities in hoge volgorde worden als volgt ingesteld op basis van het type linkeroperand:
Als de linkeroperand van het type
int
is oflong
, voert de operator voor de rechter shift een rekenkundige verschuiving uit: de waarde van de meest significante bit (de tekenbit) van de linkeroperand wordt doorgegeven aan de lege bitposities in hoge volgorde. Dat wil gezegd: de lege bitposities in hoge volgorde worden ingesteld op nul als de linkeroperand niet-negatief is en is ingesteld op één als deze negatief is.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
Als de linkeroperand van het type
uint
is ofulong
, voert de operator van rechts-shift een logische verschuiving uit: de lege bitposities in hoge volgorde worden altijd ingesteld op nul.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
Notitie
Gebruik de niet-ondertekende operator voor rechtse shift om een logische shift uit te voeren op operanden van ondertekende gehele getallen. Dit is de voorkeur om een linkeroperand naar een niet-ondertekend type te casten en vervolgens het resultaat van een dienstbewerking terug te gieten naar een ondertekend type.
Unsigned right-shift operator >>>
De operator is beschikbaar in C# 11 en hoger en verplaatst de >>>
linkeroperand naar rechts door het aantal bits dat is gedefinieerd door de rechteroperand. Zie het aantal diensten van de sectie Shift-operatoren voor informatie over hoe de rechteroperand het aantal diensten definieert.
De >>>
operator voert altijd een logische verschuiving uit. Dat wil gezegd: de lege bitposities in hoge volgorde worden altijd ingesteld op nul, ongeacht het type van de linkeroperand. De >>
operator voert een rekenkundige verschuiving uit (dat wil gezegd, de waarde van de meest significante bit wordt doorgegeven aan de lege bitposities in hoge volgorde) als de linkeroperand van een ondertekend type is. In het volgende voorbeeld ziet u het verschil tussen >>
en >>>
operators voor een negatieve operand aan de linkerkant:
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
Logische AND-operator &
De &
operator berekent de bitsgewijze logische EN van de bijbehorende integrale operanden:
uint a = 0b_1111_1000;
uint b = 0b_1001_1101;
uint c = a & b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 10011000
Voor bool
operanden berekent de &
operator de logische EN van de operanden. De unaire &
operator is het adres van de operator.
Logische exclusieve OR-operator ^
De ^
operator berekent de bitwise logische exclusieve OR, ook wel de bitwise logische XOR genoemd, van de integrale operanden:
uint a = 0b_1111_1000;
uint b = 0b_0001_1100;
uint c = a ^ b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 11100100
Voor bool
operanden berekent de ^
operator de logische exclusieve OF van de operanden.
Logische OF-operator |
De |
operator berekent de bitsgewijze logische OR van de bijbehorende integrale operanden:
uint a = 0b_1010_0000;
uint b = 0b_1001_0001;
uint c = a | b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 10110001
Voor bool
operanden berekent de |
operator de logische OR van de operanden.
Samengestelde toewijzing
Voor een binaire operator op
, een samengestelde toewijzingsexpressie van het formulier
x op= y
is gelijk aan
x = x op y
behalve dat dit x
slechts eenmaal wordt geëvalueerd.
In het volgende voorbeeld ziet u het gebruik van samengestelde toewijzingen met bitsgewijze operatoren en shiftoperators:
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}");
Vanwege numerieke promoties is het resultaat van de op
bewerking mogelijk niet impliciet converteerbaar naar het type T
x
. In dat geval op
is een vooraf gedefinieerde operator en het resultaat van de bewerking expliciet converteerbaar naar het type T
x
, is een samengestelde toewijzingsexpressie van het formulier x op= y
gelijk aan x = (T)(x op y)
, behalve dat het x
slechts eenmaal wordt geëvalueerd. In het volgende voorbeeld ziet u dat gedrag:
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
Operatorprioriteit
In de volgende lijst worden bitsgewijze operatoren geordeld en worden operatoren verplaatst vanaf de hoogste prioriteit tot de laagste:
- Bitsgewijze complementoperator
~
- Shift-operatoren
<<
,>>
en>>>
- Logische AND-operator
&
- Logische exclusieve OR-operator
^
- Logische OF-operator
|
Gebruik haakjes, ()
om de volgorde van evaluatie te wijzigen die wordt opgelegd door de prioriteit van de operator:
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}");
Zie de sectie Operatorprioriteit van het artikel C#-operators voor de volledige lijst met C#-operators die zijn gerangschikt op prioriteitsniveau.
Aantal shifts van de shiftoperators
Voor de x << count
, x >> count
en x >>> count
expressies is het werkelijke aantal diensten afhankelijk van x
het type als volgt:
Als het type
x
isint
ofuint
, wordt het aantal diensten gedefinieerd door de vijf bits met lage volgorde van de rechteroperand. Dat wil gezegd, het aantal diensten wordt berekend vancount & 0x1F
(ofcount & 0b_1_1111
).Als het type
x
islong
ofulong
, wordt het aantal diensten gedefinieerd door de lage volgorde zes bits van de rechteroperand. Dat wil gezegd, het aantal diensten wordt berekend vancount & 0x3F
(ofcount & 0b_11_1111
).
In het volgende voorbeeld ziet u dat gedrag:
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
Notitie
Zoals in het voorgaande voorbeeld wordt weergegeven, kan het resultaat van een dienstbewerking niet nul zijn, zelfs als de waarde van de rechteroperand groter is dan het aantal bits in de linkeroperand.
Logische operators inventariseren
De ~
operators , &
en |
^
operators worden ook ondersteund door elk opsommingstype. Voor operanden van hetzelfde opsommingstype wordt een logische bewerking uitgevoerd op de bijbehorende waarden van het onderliggende integrale type. Voor een x
en y
van een opsommingstype T
met een onderliggend type U
produceert de x & y
expressie bijvoorbeeld hetzelfde resultaat als de (T)((U)x & (U)y)
expressie.
Normaal gesproken gebruikt u bitwise logische operators met een opsommingstype dat is gedefinieerd met het kenmerk Vlaggen . Zie de sectie Opsommingstypen als bitvlagken van het artikel Opsommingstypen voor meer informatie.
Overbelasting van operatoren
Een door de gebruiker gedefinieerd type kan de ~
operatoren , , <<
, >>
, >>>
en ^
&
|
operators overbelasten. Wanneer een binaire operator overbelast is, wordt de bijbehorende operator voor samengestelde toewijzing ook impliciet overbelast. Een door de gebruiker gedefinieerd type kan een samengestelde toewijzingsoperator niet expliciet overbelasten.
Als een door de gebruiker gedefinieerd type T
de <<
, >>
of >>>
operator overbelast, moet het type van de linkeroperand zijn T
. In C# 10 en eerder moet het type rechteroperand zijn int
; vanaf C# 11 kan het type van de rechteroperand van een overbelaste ploegenoperator elk type zijn.
C#-taalspecificatie
Zie de volgende secties van de C#-taalspecificatie voor meer informatie:
- Bitsgewijze complementoperator
- Shift-operatoren
- Logische operators
- Samengestelde toewijzing
- Numerieke promoties
- C# 11 - Ontspannen ploegenvereisten
- C# 11 - Logische operator voor right-shift