这些数值运算实际上让你可以操纵变量中的各个位;考虑到 C 是如此底层的语言,这也合情合理151。
如果你不熟悉按位运算,维基百科上有一篇很好的按位运算条目152。
这些运算中的每一个,都会先对操作数(此时必须是整型)进行寻常算术转换,然后执行相应的按位运算。
| 运算 | 运算符 | 示例 |
|---|---|---|
| 与(AND) | & |
a = b & c |
| 或(OR) | | |
a = b | c |
| 异或(XOR) | ^ |
a = b ^ c |
| 非(NOT) | ~ |
a = ~c |
注意它们与布尔运算符 && 和 || 有多么相似。
它们也有类似 += 和 -= 的赋值简写形式:
| 运算符 | 示例 | 长写等价形式 |
|---|---|---|
&= |
a &= c |
a = a & c |
|= |
a |= c |
a = a | c |
^= |
a ^= c |
a = a ^ c |
对这些运算,会先对每个操作数(必须是整型)进行整型提升,然后执行按位移位。结果的类型是提升后的左操作数的类型。
新移入的位用 0 填充,可能的例外在下文“实现定义的行为”中说明。
| 运算 | 运算符 | 示例 |
|---|---|---|
| 左移 | << |
a = b << c |
| 右移 | >> |
a = b >> c |
移位也有同样类似的简写形式:
| 运算符 | 示例 | 长写等价形式 |
|---|---|---|
>>= |
a >>= c |
a = a >> c |
<<= |
a <<= c |
a = a << c |
注意未定义行为:不要移位负数,也不要让移位量大于提升后左操作数的大小。
还要注意实现定义的行为:如果你右移一个负数,结果是实现定义的。(右移有符号 int 完全没问题,只要确保它是正数。)