Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Os operadores bit a bit e de deslocamento incluem complemento bit a bit unário, deslocamento binário para a esquerda e a direita, deslocamento sem sinal para a direita e os operadores binários lógicos AND, OR e OR exclusivo. Esses operadores assumem operandos dos tipos numéricos integrais ou do tipo char .
- Operador unário
~(complemento bit a bit) - Operadores binários
<<(deslocamento para a esquerda),>>(deslocamento para a direita) e>>>(sem sinal de deslocamento para a direita) - Operadores binários
&(AND lógico),|(OR lógico) e^(OR exclusivo lógico)
Esses operadores são definidos para os tipos int, uint, long, ulong, nint e nuint. Quando ambos os operandos são de outros tipos integrais (sbyte, byte, short, ushort ou char), seus valores são convertidos no tipo int, que também é o tipo de resultado de uma operação. Quando os operandos são de tipos integrais diferentes, seus valores são convertidos no tipo integral mais próximo que o contém. Para saber mais, confira a seção Promoções numéricas da Especificação da linguagem C#. Os operadores compostos (como >>=) não convertem seus argumentos em int ou têm o tipo de resultado como int.
Os operadores &, | e ^ também são definidos para os operandos do tipo bool. Para obter mais informações, veja Operadores lógicos boolianos.
As operações de deslocamento e bit a bit nunca causam estouro e produzem os mesmos resultados nos contextos marcados e desmarcados.
Operador de complemento bit a bit ~
O operador ~ produz um complemento bit a bit de seu operando invertendo cada bit:
uint a = 0b_0000_1111_0000_1111_0000_1111_0000_1100;
uint b = ~a;
Console.WriteLine(Convert.ToString(b, toBase: 2));
// Output:
// 11110000111100001111000011110011
Você também pode usar o símbolo ~ para declarar finalizadores. Para mais informações, consulte Finalizadores.
Operador de deslocamento à esquerda <<
O operador << desloca para esquerda o operando à esquerda pelo número de bits definido pelo seu operando à direita. Para saber mais sobre como o operando à direita define a contagem de deslocamento, veja a seção Contagem de deslocamento dos operadores de deslocamento.
A operação de deslocamento à esquerda descarta os bits de ordem superior que estão fora do intervalo do tipo de resultado e define as posições de bits vazios de ordem inferior como zero, como mostra o exemplo a seguir:
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
Como os operadores de deslocamento são definidos apenas para os tipos int, uint, long e ulong, o resultado de uma operação sempre contém pelo menos 32 bits. Se o operando à esquerda for de outro tipo integral (sbyte, byte, short, ushort ou char), seu valor será convertido no tipo int, como mostra o exemplo a seguir:
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
Operador de deslocamento à direita >>
O operador >> desloca para direita o operando à esquerda pelo número de bits definido pelo seu operando à direita. Para saber mais sobre como o operando à direita define a contagem de deslocamento, veja a seção Contagem de deslocamento dos operadores de deslocamento.
A operação de deslocamento à direita descarta os bits de ordem inferior, como mostra o exemplo a seguir:
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
As posições vazias de bit de ordem superior são definidas com base no tipo do operando à esquerda da seguinte maneira:
Se o operando à esquerda for do tipo
intoulong, o operador de deslocamento à direita executará um deslocamento aritmético: o valor do bit mais significativo (o bit de sinal) do operando à esquerda é propagado para as posições vazias de bits de ordem superior. Ou seja, as posições vazias de bit de ordem superior são definidas como zero se o operando à esquerda for positivo e definidas como um se ele for negativo.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: 11110000000000000000000000000000Se o operando à esquerda for do tipo
uintouulong, o operador de deslocamento à direita executará um deslocamento lógico: as posições vazias de bit de ordem superior são sempre definidas como zero.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
Observação
Use o operador de deslocamento à direita sem sinal para executar um deslocamento lógica em operandos de tipos inteiros com sinal. A mudança lógica é preferencial. Evite converter o operando esquerdo em um tipo sem sinal e, em seguida, converter o resultado de uma operação de deslocamento de volta para um tipo assinado.
Operador de deslocamento para a direita sem sinal >>>
O operador >>> desloca para direita o operando à esquerda pelo número de bits definido pelo seu operando à direita. Para saber mais sobre como o operando à direita define a contagem de deslocamento, veja a seção Contagem de deslocamento dos operadores de deslocamento.
O operador >>> sempre realiza um deslocamento lógico. Ou seja, as posições de bits vazias de alta ordem são sempre definidas como zero, independentemente do tipo do operando à esquerda. O operador >> executa um deslocamento aritmético (ou seja, o valor do bit mais significativo é propagado para as posições de bit vazias de alta ordem) se o operando à esquerda for de um tipo assinado. O seguinte exemplo demonstra a diferença entre os operadores >> e >>> para um operando à esquerda negativo:
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
Operador AND lógico &
O operador & computa o AND lógico bit a bit de seus operandos integrais:
uint a = 0b_1111_1000;
uint b = 0b_1001_1101;
uint c = a & b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 10011000
Para operandos bool, o operador & computa o AND lógico de seus operandos. O operador & unário é o operador address-of.
Operador OR exclusivo lógico ^
O operador ^ computa o OR exclusivo lógico bit a bit, também conhecido como o XOR lógico bit a bit, de seus operandos integrais:
uint a = 0b_1111_1000;
uint b = 0b_0001_1100;
uint c = a ^ b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 11100100
Para operandos bool, o operador ^ computa o OR exclusivo lógico de seus operandos.
Operador OR lógico |
O operador | computa o OR lógico bit a bit de seus operandos integrais:
uint a = 0b_1010_0000;
uint b = 0b_1001_0001;
uint c = a | b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 10110001
Para operandos bool, o operador | computa o OR lógico de seus operandos.
Atribuição composta
Para um operador binário op, uma expressão de atribuição composta do formato
x op= y
É equivalente a
x = x op y
Exceto que x é avaliado apenas uma vez.
O seguinte exemplo demonstra o uso da atribuição composta com operadores bit a bit e de deslocamento:
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}");
Devido a promoções numéricas, o resultado da operação op pode não ser implicitamente conversível no tipo T de x. Nesse caso, se op for um operador predefinido e o resultado da operação for explicitamente convertido no tipo T de x, uma expressão de atribuição composta da forma x op= y será equivalente a x = (T)(x op y), exceto que x será avaliada apenas uma vez. O exemplo a seguir demonstra esse comportamento:
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
Precedência do operador
A lista a seguir ordena os operadores lógicos, começando da mais alta precedência até a mais baixa:
- Operador de complemento bit a bit
~ - Operadores de deslocamento
<<,>>e>>> - Operador AND lógico
& - Operador OR exclusivo lógico
^ - Operador OR lógico
|
Use parênteses, (), para alterar a ordem de avaliação imposta pela precedência do operador:
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}");
Para obter a lista completa de operadores C# ordenados por nível de precedência, consulte a seção Precedência de operador do artigo Operadores C#.
Contagem de deslocamento dos operadores de deslocamento
Para as expressões x << count, x >> count e x >>> count, a contagem real de deslocamento depende do tipo de x da seguinte maneira:
Se o tipo de
xforintouuint, os cinco bits de ordem inferior do operando à direita definirão a contagem de deslocamento. Ou seja, a contagem de deslocamentos é calculada a partir decount & 0x1F(oucount & 0b_1_1111).Se o tipo de
xforlongouulong, os seis bits de ordem inferior do operando à direita definirão a contagem de deslocamento. Ou seja, a contagem de deslocamentos é calculada a partir decount & 0x3F(oucount & 0b_11_1111).
O exemplo a seguir demonstra esse comportamento:
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
Observação
Como mostra o exemplo anterior, o resultado de uma operação de deslocamento pode ser diferente de zero mesmo que o valor do operando à direita seja maior do que o número de bits no operando à esquerda.
Operadores lógicos de enumeração
Cada tipo de enumeração dá suporte aos operadores ~, &, | e ^. Para operandos do mesmo tipo de enumeração, uma operação lógica é executada nos valores correspondentes do tipo integral subjacente. Por exemplo, para qualquer x e y de um tipo de enumeração T com um tipo subjacente U, a expressão x & y produz o mesmo resultado que a expressão (T)((U)x & (U)y).
Geralmente, você usa os operadores lógicos bit a bit com um tipo de enumeração definido com o atributo sinalizadores. Para obter mais informações, veja a seção Tipos de enumeração como sinalizadores de bit do artigo Tipos de enumeração.
Capacidade de sobrecarga do operador
Um tipo definido pelo usuário pode sobrecarregar os operadores ~, <<, >>, >>>, &, |e ^. Quando um operador binário está sobrecarregado, o operador de atribuição composta correspondente também é implicitamente sobrecarregado. A partir do C# 14, um tipo definido pelo usuário pode sobrecarregar explicitamente os operadores de atribuição composta para fornecer uma implementação mais eficiente. Normalmente, um tipo sobrecarrega esses operadores porque o valor pode ser atualizado no local, em vez de alocar uma nova instância para armazenar o resultado da operação binária. Se um tipo não fornecer uma sobrecarga explícita, o compilador gerará a sobrecarga implícita.
Se um tipo definido pelo usuário T sobrecarregar o operador <<, >> ou >>>, o tipo do operando à esquerda deverá ser T. No C# 10 e anterior, o tipo do operando à direita deve ser int; o tipo do operando à direita de um operador de deslocamento sobrecarregado pode ser qualquer.
Especificação da linguagem C#
Para obter mais informações, confira as seguintes seções da especificação da linguagem C#:
- Operador de complemento bit a bit
- Operadores shift
- Operadores lógicos
- Atribuição composta
- Promoções numéricas
- Requisitos de turno relaxados
- Operador de deslocamento lógico para a direita
- Atribuição composta definida pelo usuário