位运算符和移位运算符(C# 参考)Bitwise and shift operators (C# reference)

以下运算符使用整数类型char 类型的操作数执行位运算或移位运算:The following operators perform bitwise or shift operations with operands of the integral numeric types or the char type:

这些运算符是针对 intuintlongulong 类型定义的。Those operators are defined for the int, uint, long, and ulong types. 如果两个操作数都是其他整数类型(sbytebyteshortushortchar),它们的值将转换为 int 类型,这也是一个运算的结果类型。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. 如果操作数是不同的整数类型,它们的值将转换为最接近的包含整数类型。When operands are of different integral types, their values are converted to the closest containing integral type. 有关详细信息,请参阅 C# 语言规范数值提升部分。For more information, see the Numeric promotions section of the C# language specification.

&|^ 运算符也是为 bool 类型的操作数定义的。The &, |, and ^ operators are also defined for operands of the bool type. 有关详细信息,请参阅布尔逻辑运算符For more information, see Boolean logical operators.

位运算和移位运算永远不会导致溢出,并且不会在已检查和未检查的上下文中产生相同的结果。Bitwise and shift operations never cause overflow and produce the same results in checked and unchecked contexts.

按位求补运算符 ~Bitwise complement operator ~

~ 运算符通过反转每个位产生其操作数的按位求补: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

也可以使用 ~ 符号来声明终结器。You can also use the ~ symbol to declare finalizers. 有关详细信息,请参阅终结器For more information, see Finalizers.

左移位运算符 <<Left-shift operator <<

<< 运算符将其左侧操作数向左移动右侧操作数定义的位数The << operator shifts its left-hand operand left by the number of bits defined by its right-hand operand.

左移运算会放弃超出结果类型范围的高阶位,并将低阶空位位置设置为零,如以下示例所示: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

由于移位运算符仅针对 intuintlongulong 类型定义,因此运算的结果始终包含至少 32 位。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. 如果左侧操作数是其他整数类型(sbytebyteshortushortchar),则其值将转换为 int 类型,如以下示例所示:If the left-hand 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

有关 << 运算符的右侧操作数如何定义移位计数的信息,请参阅移位运算符的移位计数部分。For information about how the right-hand operand of the << operator defines the shift count, see the Shift count of the shift operators section.

右移位运算符 >>Right-shift operator >>

>> 运算符将其左侧操作数向右移动右侧操作数定义的位数The >> operator shifts its left-hand operand right by the number of bits defined by its right-hand operand.

右移位运算会放弃低阶位,如以下示例所示: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

高顺序空位位置是根据左侧操作数类型设置的,如下所示:The high-order empty bit positions are set based on the type of the left-hand operand as follows:

  • 如果左侧操作数的类型是 intlong,则右移运算符将执行 算术移位:左侧操作数的最高有效位(符号位)的值将传播到高顺序空位位置。If the left-hand 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 left-hand operand is propagated to the high-order empty bit positions. 也就是说,如果左侧操作数为非负,高顺序空位位置设置为零,如果为负,则将该位置设置为 1。That is, the high-order empty bit positions are set to zero if the left-hand 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
    
  • 如果左侧操作数的类型是 uintulong,则右移运算符执行逻辑移位:高顺序空位位置始终设置为零。 If the left-hand 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
    

有关 >> 运算符的右侧操作数如何定义移位计数的信息,请参阅移位运算符的移位计数部分。For information about how the right-hand operand of the >> operator defines the shift count, see the Shift count of the shift operators section.

逻辑 AND 运算符 &Logical AND operator &

& 运算符计算其整型操作数的位逻辑 AND:The & operator computes the bitwise logical AND of its integral operands:

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

对于 bool 操作数,& 运算符对其操作数执行逻辑 AND 运算。For bool operands, the & operator computes the logical AND of its operands. 一元 & 运算符是 address-of 运算符The unary & operator is the address-of operator.

逻辑异或运算符 ^Logical exclusive OR operator ^

^ 运算符计算其整型操作数的位逻辑异或,也称为位逻辑 XOR:The ^ operator computes the bitwise logical exclusive OR, also known as the bitwise logical XOR, of its integral operands:

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

对于 bool 操作数,^ 运算符对其操作数执行逻辑异或运算。For bool operands, the ^ operator computes the logical exclusive OR of its operands.

逻辑或运算符 |Logical OR operator |

| 运算符计算其整型操作数的位逻辑 OR:The | operator computes the bitwise logical OR of its integral operands:

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

对于 bool 操作数,| 运算符对其操作数执行逻辑 OR 运算。For bool operands, the | operator computes the logical OR of its operands.

复合赋值Compound assignment

对于二元运算符 op,窗体的复合赋值表达式For a binary operator op, a compound assignment expression of the form

x op= y

等效于is equivalent to

x = x op y

不同的是 x 只计算一次。except that x is only evaluated once.

以下示例演示了使用位运算符和移位运算符的复合赋值的用法: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}");

由于数值提升op 运算的结果可能不会隐式转换为 xT 类型。Because of numeric promotions, the result of the op operation might be not implicitly convertible to the type T of x. 在这种情况下,如果 op 是预定义的运算符并且运算的结果可以显式转换为 x 的类型 T,则形式为 x op= y 的复合赋值表达式等效于 x = (T)(x op y),但 x 仅计算一次。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. 以下示例演示了该行为: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

运算符优先级Operator precedence

以下列表按位运算符和移位运算符从最高优先级到最低优先级排序:The following list orders bitwise and shift operators starting from the highest precedence to the lowest:

  • 按位求补运算符 ~Bitwise complement operator ~
  • 移位运算符 <<>>Shift operators << and >>
  • 逻辑与运算符 &Logical AND operator &
  • 逻辑异或运算符 ^Logical exclusive OR operator ^
  • 逻辑或运算符 |Logical OR operator |

使用括号 () 可以更改运算符优先级决定的计算顺序: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}");

要了解按优先级排序的完整 C# 运算符列表,请参阅 C# 运算符一文中的运算符优先级部分。For the complete list of C# operators ordered by precedence level, see the Operator precedence section of the C# operators article.

移位运算符的移位计数Shift count of the shift operators

对于移位运算符 <<>>,右侧操作数的类型必须为 int,或具有预定义隐式数值转换int 的类型。For the shift operators << and >>, the type of the right-hand operand must be int or a type that has a predefined implicit numeric conversion to int.

对于 x << countx >> count 表达式,实际移位计数取决于 x 的类型,如下所示:For the x << count and x >> count expressions, the actual shift count depends on the type of x as follows:

  • 如果 x 的类型为 intuint,则移位计数由右侧操作数的低阶五位定义。 If the type of x is int or uint, the shift count is defined by the low-order five bits of the right-hand operand. 也就是说,移位计数通过 count & 0x1F(或 count & 0b_1_1111)计算得出。That is, the shift count is computed from count & 0x1F (or count & 0b_1_1111).

  • 如果 x 的类型为 longulong,则移位计数由右侧操作数的低阶六位定义。 If the type of x is long or ulong, the shift count is defined by the low-order six bits of the right-hand operand. 也就是说,移位计数通过 count & 0x3F(或 count & 0b_11_1111)计算得出。That is, the shift count is computed from count & 0x3F (or count & 0b_11_1111).

以下示例演示了该行为: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

备注

如前例所示,即使右侧操作符的值大于左侧操作符中的位数,移位运算的结果也不可为零。As the preceding example shows, the result of a shift operation can be non-zero even if the value of the right-hand operand is greater than the number of bits in the left-hand operand.

枚举逻辑运算符Enumeration logical operators

所有枚举类型还支持 ~&|^ 运算符。The ~, &, |, and ^ operators are also supported by any enumeration type. 对于相同枚举类型的操作数,对底层整数类型的相应值执行逻辑运算。For operands of the same enumeration type, a logical operation is performed on the corresponding values of the underlying integral type. 例如,对于具有底层类型 U 的枚举类型 T 的任何 xyx & y 表达式生成与 (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.

通常使用具有枚举类型的位逻辑运算符,该枚举类型使用 Flags 特性定义。You typically use bitwise logical operators with an enumeration type that is defined with the Flags attribute. 有关详细信息,请参阅枚举类型一文的作为位标记的枚举类型部分。For more information, see the Enumeration types as bit flags section of the Enumeration types article.

运算符可重载性Operator overloadability

用户定义的类型可以重载~<<>>&|^ 运算符。A user-defined type can overload the ~, <<, >>, &, |, and ^ operators. 重载二元运算符时,对应的复合赋值运算符也会隐式重载。When a binary operator is overloaded, the corresponding compound assignment operator is also implicitly overloaded. 用户定义类型不能显式重载复合赋值运算符。A user-defined type cannot explicitly overload a compound assignment operator.

如果用户定义类型 T 重载 <<>> 运算符,则左侧操作数的类型必须为 T 且右侧操作数的类型必须为 intIf a user-defined type T overloads the << or >> operator, the type of the left-hand operand must be T and the type of the right-hand operand must be int.

C# 语言规范C# language specification

有关更多信息,请参阅 C# 语言规范的以下部分:For more information, see the following sections of the C# language specification:

另请参阅See also