Operadores de desplazamiento y bit a bit (Referencia de C#)Bitwise and shift operators (C# Reference)

Los siguientes operadores realizan operaciones de desplazamiento o bit a bit con operandos de tipo entero:The following operators perform bitwise or shift operations with operands of the integral types:

Estos operadores se definen para los tipos int, uint, long y ulong.Those operators are defined for the int, uint, long, and ulong types. Cuando ambos operandos son de otro tipo entero (sbyte, byte, short, ushort o char), sus valores se convierten en el tipo int, que también es el tipo de resultado de una operación.When both operands are of other integral types (sbyte, byte, short, ushort, or char), their values are converted to the int type, which is also the result type of an operation. Cuando los operandos son de tipo entero diferente, sus valores se convierten en el tipo entero más cercano que contenga.When operands are of different integral types, their values are converted to the closest containing integral type. Para obtener más información, vea la sección Promociones numéricas de Especificación del lenguaje C#.For more information, see the Numeric promotions section of the C# language specification.

Los operadores &, | y ^ también se definen para los operandos de tipo bool.The &, |, and ^ operators are also defined for the operands of the bool type. Para obtener más información, vea Operadores lógicos booleanos.For more information, see Boolean logical operators.

Las operaciones de desplazamiento y bit a bit nunca producen desbordamiento y generan los mismos resultados en contextos Checked y Unchecked.Bitwise and shift operations never cause overflow and produce the same results in checked and unchecked contexts.

Operador de complemento bit a bit ~Bitwise complement operator ~

El operador ~ genera un complemento bit a bit de su operando al invertir cada bit:The ~ operator produces a bitwise complement of its operand by reversing each bit:

uint a = 0b_0000_1111_0000_1111_0000_1111_0000_1100;
uint b = ~a;
Console.WriteLine(Convert.ToString(b, toBase: 2));
// Output:
// 11110000111100001111000011110011

También se puede usar el símbolo ~ para declarar finalizadores.You can also use the ~ symbol to declare finalizers. Para obtener más información, vea Finalizadores.For more information, see Finalizers.

Operador de desplazamiento izquierdo <<Left-shift operator <<

El operador << desplaza su primer operando a la izquierda el número de bits definido por su segundo operando.The << operator shifts its first operand left by the number of bits defined by its second operand.

La operación de desplazamiento izquierdo descarta los bits de orden superior que están fuera del rango del tipo de resultado y establece las posiciones de bits vacías de orden inferior en cero, como se muestra en el ejemplo siguiente:The left-shift operation discards the high-order bits that are outside the range of the result type and sets the low-order empty bit positions to zero, as the following example shows:

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

Dado que los operadores de desplazamiento solo se definen para los tipos int, uint, long y ulong, el resultado de una operación siempre contiene al menos 32 bits.Because the shift operators are defined only for the int, uint, long, and ulong types, the result of an operation always contains at least 32 bits. Si el primer operando es de otro tipo entero (sbyte, byte, short, ushort o char), su valor se convierte en el tipo int, como se muestra en el ejemplo siguiente:If the first operand is of another integral type (sbyte, byte, short, ushort, or char), its value is converted to the int type, as the following example shows:

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

Para obtener información sobre cómo el segundo operando del operador << define el recuento de desplazamiento, vea la sección Recuento de desplazamiento de los operadores de desplazamiento.For information about how the second operand of the << operator defines the shift count, see the Shift count of the shift operators section.

Operador de desplazamiento derecho >>Right-shift operator >>

El operador >> desplaza su primer operando a la derecha el número de bits definido por su segundo operando.The >> operator shifts its first operand right by the number of bits defined by its second operand.

La operación de desplazamiento derecho descarta los bits de orden inferior, como se muestra en el ejemplo siguiente:The right-shift operation discards the low-order bits, as the following example shows:

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), 4}");
// Output:
// Before: 1001
// After:    10

Las posiciones de bits vacíos de orden superior se establecen basándose en el tipo del primer operando como sigue:The high-order empty bit positions are set based on the type of the first operand as follows:

  • Si el primer operando es de tipo int o long, el operador de desplazamiento a la derecha realiza un desplazamiento aritmético: el valor del bit más significativo (el bit de signo) del primer operando se propaga a las posiciones de bits vacíos de orden superior.If the first operand is of type int or long, the right-shift operator performs an arithmetic shift: the value of the most significant bit (the sign bit) of the first operand is propagated to the high-order empty bit positions. Es decir, las posiciones de bits vacíos de orden superior se establecen en cero si el primer operando no es negativo y se establecen en uno si es negativo.That is, the high-order empty bit positions are set to zero if the first operand is non-negative and set to one if it's negative.

    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 el primer operando es de tipo uint o ulong, el operador de desplazamiento a la derecha realiza un desplazamiento lógico: las posiciones de bits vacíos de orden superior se establecen siempre en cero.If the first operand is of type uint or ulong, the right-shift operator performs a logical shift: the high-order empty bit positions are always set to 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), 32}");
    // Output:
    // Before: 10000000000000000000000000000000
    // After:     10000000000000000000000000000
    

Para obtener información sobre cómo el segundo operando del operador >> define el recuento de desplazamiento, vea la sección Recuento de desplazamiento de los operadores de desplazamiento.For information about how the second operand of the >> operator defines the shift count, see the Shift count of the shift operators section.

Operador AND lógico &Logical AND operator &

El operador & calcula el AND lógico bit a bit de sus operandos:The & operator computes the bitwise logical AND of its operands:

uint a = 0b_1111_1000;
uint b = 0b_1001_1101;
uint c = a & b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 10011000

En el caso de los operandos de tipo bool, el operador & calcula el AND lógico de sus operandos.For the operands of the bool type, the & operator computes the logical AND of its operands. El operador & unario es el operador address-of.The unary & operator is the address-of operator.

Operador IR exclusivo lógico ^Logical exclusive OR operator ^

El operador ^ calcula el OR exclusivo lógico bit a bit, también conocido como XOR lógico bit a bit, de sus operandos:The ^ operator computes the bitwise logical exclusive OR, also known as the bitwise logical XOR, of its operands:

uint a = 0b_1111_1000;
uint b = 0b_0001_1100;
uint c = a ^ b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 11100100

En el caso de los operandos de tipo bool, el operador ^ calcula el OR exclusivo lógico de sus operandos.For the operands of the bool type, the ^ operator computes the logical exclusive OR of its operands.

Operador lógico OR |Logical OR operator |

El operador | calcula el OR lógico bit a bit de sus operandos:The | operator computes the bitwise logical OR of its operands:

uint a = 0b_1010_0000;
uint b = 0b_1001_0001;
uint c = a | b;
Console.WriteLine(Convert.ToString(c, toBase: 2));
// Output:
// 10110001

En el caso de los operandos de tipo bool, el operador | calcula el OR lógico de sus operandos.For the operands of the bool type, the | operator computes the logical OR of its operands.

Asignación compuestaCompound assignment

Para un operador binario op, una expresión de asignación compuesta con el formatoFor a binary operator op, a compound assignment expression of the form

x op= y

es equivalente ais equivalent to

x = x op y

salvo que x solo se evalúa una vez.except that x is only evaluated once.

En el ejemplo siguiente se muestra el uso de la asignación compuesta con operadores de desplazamiento y bit a bit:The following example demonstrates the usage of compound assignment with bitwise and shift operators:

uint a = 0b_1111_1000;
a &= 0b_1001_1101;
Display(a);  // output: 10011000

a |= 0b_0011_0001;
Display(a);  // output: 10111001

a ^= 0b_1000_0000;
Display(a);  // output:   111001

a <<= 2;
Display(a);  // output: 11100100

a >>= 4;
Display(a);  // output:     1110

void Display(uint x) => Console.WriteLine($"{Convert.ToString(x, toBase: 2), 8}");

A causa de las promociones numéricas, el resultado de la operación op podría no ser convertible de forma implícita en el tipo T de x.Because of numeric promotions, the result of the op operation might be not implicitly convertible to the type T of x. En tal caso, si op es un operador predefinido y el resultado de la operación es convertible de forma explícita en el tipo T de x, una expresión de asignación compuesta con el formato x op= y es equivalente a x = (T)(x op y), excepto que x solo se evalúa una vez.In such a case, if op is a predefined operator and the result of the operation is explicitly convertible to the type T of x, a compound assignment expression of the form x op= y is equivalent to x = (T)(x op y), except that x is only evaluated once. En el ejemplo siguiente se muestra ese comportamiento:The following example demonstrates that behavior:

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

Prioridad de operadoresOperator precedence

En la lista siguiente se ordenan los operadores de desplazamiento y bit a bit desde la prioridad más alta a la más baja:The following list orders bitwise and shift operators starting from the highest precedence to the lowest:

  • Operador de complemento bit a bit ~Bitwise complement operator ~
  • Operadores de desplazamiento << y >>Shift operators << and >>
  • Operador AND lógico &Logical AND operator &
  • Operador OR exclusivo lógico ^Logical exclusive OR operator ^
  • Operador OR lógico |Logical OR operator |

Use los paréntesis, (), para cambiar el orden de evaluación impuesto por la prioridad de los operadores:Use parentheses, (), to change the order of evaluation imposed by operator precedence:

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 obtener la lista completa de los operadores de C# ordenados por nivel de prioridad, vea Operadores de C#.For the complete list of C# operators ordered by precedence level, see C# operators.

Recuento de desplazamiento de los operadores de desplazamientoShift count of the shift operators

En el caso de los operadores de desplazamiento << y >>, el tipo del segundo operando debe ser int o un tipo que tenga una conversión numérica implícita predefinida en int.For the shift operators << and >>, the type of the second operand must be int or a type that has a predefined implicit numeric conversion to int.

En el caso de las expresiones x << count y x >> count, el recuento de desplazamiento real depende del tipo de x, de esta forma:For the x << count and x >> count expressions, the actual shift count depends on the type of x as follows:

  • Si el tipo de x es int o uint, el recuento de desplazamiento viene definido por los cinco bits de orden inferior del segundo operando.If the type of x is int or uint, the shift count is defined by the low-order five bits of the second operand. Es decir, el valor de desplazamiento se calcula a partir de count & 0x1F (o count & 0b_1_1111).That is, the shift count is computed from count & 0x1F (or count & 0b_1_1111).

  • Si el tipo de x es long o ulong, el recuento de desplazamiento viene definido por los seis bits de orden inferior del segundo operando.If the type of x is long or ulong, the shift count is defined by the low-order six bits of the second operand. Es decir, el valor de desplazamiento se calcula a partir de count & 0x3F (o count & 0b_11_1111).That is, the shift count is computed from count & 0x3F (or count & 0b_11_1111).

En el ejemplo siguiente se muestra ese comportamiento:The following example demonstrates that behavior:

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

Operadores lógicos de enumeraciónEnumeration logical operators

Los operadores ~, &, | y ^ también se definen para cualquier tipo de enumeración.The ~, &, |, and ^ operators are also defined for any enumeration type. En el caso de los operandos del mismo tipo de enumeración, se realiza una operación lógica en los valores correspondientes del tipo entero subyacente.For the operands of the same enumeration type, a logical operation is performed on the corresponding values of the underlying integral type. Por ejemplo, para cualquier x e y de un tipo de enumeración T con un tipo subyacente U, la expresión x & y produce el mismo resultado que la expresión (T)((U)x & (U)y).For example, for any x and y of an enumeration type T with an underlying type U, the x & y expression produces the same result as the (T)((U)x & (U)y) expression.

Normalmente, los operadores lógicos bit a bit se usan con un tipo de enumeración definido con el atributo Flags.You typically use bitwise logical operators with an enumeration type which is defined with the Flags attribute. Para obtener más información, vea la sección Tipos de enumeración como marcas de bits del artículo Tipos de enumeración.For more information, see the Enumeration types as bit flags section of the Enumeration types article.

Posibilidad de sobrecarga del operadorOperator overloadability

Un tipo definido por el usuario puede sobrecargar los operadores ~, <<, >>, &, | y ^.A user-defined type can overload the ~, <<, >>, &, |, and ^ operators. Cuando se sobrecarga un operador binario, también se sobrecarga de forma implícita el operador de asignación compuesta correspondiente.When a binary operator is overloaded, the corresponding compound assignment operator is also implicitly overloaded. Un tipo definido por el usuario no puede sobrecargar de forma explícita un operador de asignación compuesta.A user-defined type cannot explicitly overload a compound assignment operator.

Si un tipo definido por el usuario T sobrecarga el operador << o >>, el tipo del primer operando debe ser T y el del segundo int.If a user-defined type T overloads the << or >> operator, the type of the first operand must be T and the type of the second operand must be int.

Especificación del lenguaje C#C# language specification

Para más información, vea las secciones siguientes de la Especificación del lenguaje C#:For more information, see the following sections of the C# language specification:

Vea tambiénSee also