位运算符和移位运算符 | 您所在的位置:网站首页 › 字循环移位指令的最大移位位数 › 位运算符和移位运算符 |
位运算符和移位运算符(C# 参考)
项目04/03/2023
位运算符和移位运算符包括一元位补、二进制左移和右移、无符号右移、二进制逻辑 AND、OR 和异或运算符。 这些操作数采用整型数值类型或字符型操作数。 一元 ~(按位求补)运算符 二进制 (右移)和 >>>(无符号右移)运算符 二进制 &(逻辑 AND)、|(逻辑 OR)和 ^(逻辑异或)运算符这些运算符是针对 int、uint、long 和 ulong 类型定义的。 如果两个操作数都是其他整数类型(sbyte、byte、short、ushort 或 char),它们的值将转换为 int 类型,这也是一个运算的结果类型。 如果操作数是不同的整数类型,它们的值将转换为最接近的包含整数类型。 有关详细信息,请参阅 C# 语言规范的数值提升部分。 复合运算符(如 >>=)不会将其参数转换为 int,也不会具有结果类型 int。 &、| 和 ^ 运算符也是为 bool 类型的操作数定义的。 有关详细信息,请参阅布尔逻辑运算符。 位运算和移位运算永远不会导致溢出,并且不会在已检查和未检查的上下文中产生相同的结果。 按位求补运算符 ~~ 运算符通过反转每个位产生其操作数的按位求补: uint a = 0b_0000_1111_0000_1111_0000_1111_0000_1100; uint b = ~a; Console.WriteLine(Convert.ToString(b, toBase: 2)); // Output: // 11110000111100001111000011110011也可以使用 ~ 符号来声明终结器。 有关详细信息,请参阅终结器。 左移位运算符 2; Console.WriteLine($"After: {Convert.ToString(y, toBase: 2).PadLeft(4, '0'), 4}"); // Output: // Before: 1001 // After: 0010高顺序空位位置是根据左侧操作数类型设置的,如下所示: 如果左侧操作数的类型是 int 或 long,则右移运算符将执行 算术移位:左侧操作数的最高有效位(符号位)的值将传播到高顺序空位位置。 也就是说,如果左侧操作数为非负,高顺序空位位置设置为零,如果为负,则将该位置设置为 1。 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如果左侧操作数的类型是 uint 或 ulong,则右移运算符执行逻辑移位:高顺序空位位置始终设置为零。 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注意 使用无符号右移运算符可以对带符号整数类型的操作数执行逻辑移位。 这优于将左侧操作数强制转换为无符号类型,然后将移位操作的结果强制转换回带符号类型。 无符号右移运算符 >>>在 C# 11 及更高版本中可用,>>> 运算符将其左侧操作数向右移动其右侧操作数定义的位数。 有关右侧操作数如何定义移位计数的信息,请参阅移位运算符的移位计数部分。 >>> 运算符始终执行逻辑移位。 也就是说,无论左侧操作数的类型如何,高顺序空位位置始终设置为零。 如果左侧操作数是带符号类型,>> 运算符将执行算术移位(即,最高有效位的值传播到高顺序空位位置)。 以下示例演示了对于负左操作数,>> 和 >>> 运算符之间的差别: 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 逻辑“与”运算符 && 运算符计算其整型操作数的位逻辑 AND: 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 运算。 一元 & 运算符是 address-of 运算符。 逻辑异或运算符 ^^ 运算符计算其整型操作数的位逻辑异或,也称为位逻辑 XOR: uint a = 0b_1111_1000; uint b = 0b_0001_1100; uint c = a ^ b; Console.WriteLine(Convert.ToString(c, toBase: 2)); // Output: // 11100100对于 bool 操作数,^ 运算符对其操作数执行逻辑异或运算。 逻辑或运算符 || 运算符计算其整型操作数的位逻辑 OR: 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 运算。 复合赋值对于二元运算符 op,窗体的复合赋值表达式 x op= y等效于 x = x op y不同的是 x 只计算一次。 以下示例演示了使用位运算符和移位运算符的复合赋值的用法: 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 = 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}");由于数值提升,op 运算的结果可能不会隐式转换为 x 的 T 类型。 在这种情况下,如果 op 是预定义的运算符并且运算的结果可以显式转换为 x 的类型 T,则形式为 x op= y 的复合赋值表达式等效于 x = (T)(x op y),但 x 仅计算一次。 以下示例演示了该行为: byte x = 0b_1111_0001; int b = x 逻辑与运算符 & 逻辑异或运算符 ^ 逻辑或运算符 |使用括号 () 可以更改运算符优先级决定的计算顺序: 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# 运算符一文中的运算符优先级部分。 移位运算符的移位计数对于内置移位运算符 和 >>>,右侧操作数的类型必须为 int,或具有预定义隐式数值转换为 int 的类型。 对于 x > count 和 x >>> count 表达式,实际移位计数取决于 x 的类型,如下所示: 如果 x 的类型为 int 或 uint,则移位计数由右侧操作数的低阶五位定义。 也就是说,移位计数通过 count & 0x1F(或 count & 0b_1_1111)计算得出。 如果 x 的类型为 long 或 ulong,则移位计数由右侧操作数的低阶六位定义。 也就是说,移位计数通过 count & 0x3F(或 count & 0b_11_1111)计算得出。 以下示例演示了该行为: int count1 = 0b_0000_0001; int count2 = 0b_1110_0001; int a = 0b_0001; Console.WriteLine($"{a} 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} |
CopyRight 2018-2019 实验室设备网 版权所有 |