#cshap#operator

csharp 中 int 、uint、long 、ulong 可以直接参与位运算, 对于 sbyte 、byte 、short、ushort、char 类型则先转换成 int 来参与位运算。如果操作数是不同类型的,则转换成距离二者最近的类型参与运算, 转换规则可以参看 数值提升

位运算符有:

  • 按位取反 ~
  • 左移<< 、右移 >> , 也被称为算术位移
  • 无符号右移 >>>, 也被称为逻辑位移, 在 c# 11.0 以上可 #csharp11
  • &、或|、异或^

位移运算规则

为了便于描述, 做出以下说明:

  • a 为移位的对象
  • c 为移位的位数
  • bitwidth 为 a 在内存中占据的 bit 位宽, 假如 a 是 int 类型, 则占据 32 位宽

a 以连续 0/1 串的形式存储在内存中, 可以将占有的内存片段称为内存盒子。无论左移还是右移, 等价于整体向一个方向移动, 内存盒子出现空位, 空位会被填上 0 或者 1, 移出存储盒子的位则被抛弃。注意:实际运算并不存在位的移动, 只是为了方便理解进行的形象化描述。当所有的位移出存储盒子, 则恢复为原来的值, 所以位移具有周期性, 周期为 bitwidth。

左移

左移操作, 存储盒子右侧出现空位, 并且填充 0, 移动 bitwidth - 1 次, 最右侧的位移动到最左侧, 再移动一次则恢复最初的值, 如此往复。

右移

逻辑位移和算术位移在空位填补上存在区别, 正数和负数的空位填补上存在区别。

正数

算术位移和逻辑位移的行为一致。存储盒子左侧出现空位, 并且用 0 填充, 移动 bitwidth - 1 次, 最高位移动到最低位。再移动一次则恢复最初的值, 如此往复。

负数

算术位移和逻辑位移的行为有区别。存储盒子左侧出现空位, 逻辑位移使用 0 来填充, 算术位移用 1 。移动 bitwidth - 1 次, 最高位移动到最低位。再移动一次则恢复最初的值, 如此往复。

复合赋值

位移操作通用支持符合复制。形如 x op= y 等价于 x = x op y, op 可以是&>><<>>>

枚举逻辑运算符

所有枚举类型还支持 ~、&、| 和 ^ 运算符。 对于相同枚举类型的操作数,对底层整数类型的相应值执行逻辑运算。 例如,对于具有底层类型 U 的枚举类型 T 的任何 x 和 y,x & y 表达式生成与 (T)((U)x & (U)y) 表达式相同的结果。