位运算符被引入C语言以方便低级数据和硬件的操作:寄存器设置、掩码、以2的幂次进行乘法和除法。它们的工作规则在8位和16位处理器时代就已经形成。
在signed类型的位移操作中经常出错,因为结果依赖于实现(算术或逻辑位移),并且在超出类型大小边界时也会导致错误。错误会导致数据损坏、计算不正确和未定义行为。
左移(<<): 等价于将值乘以2的k次 (a << k)。右侧始终填充为零。
右移(>>): 对于unsigned值,左侧填充零(逻辑位移),而对于signed值,可能会填充符号位(算术位移)或填充零(行为依赖于编译器)。
示例:
unsigned int x = 5; // 0000 0101 unsigned int y = x << 1; // 0000 1010 == 10 int z = -4; // 1111 1100 (如果是8位) int w = z >> 1; // 可能仍然是1111 1110 (-2) 或 0111 1110 (依赖于实现)
关键特性:
将负数右移>>会发生什么?
结果依赖于实现:通常是保留符号的算术位移,但标准并没有保证!
将位移量设为超过类型位数的结果是什么?
未定义行为。例如,1 << 32 对于32位类型可能产生任何结果,甚至会使程序崩溃。
可以对浮点数使用位运算符吗?
不可以,标准类型的float和double不支持位运算。仅支持整数类型。
程序员将int左移32以生成掩码——在某些平台上这会导致结果为零,而在其他平台上则可能导致不可识别的值。
优点:
缺点:
相反,使用unsigned值和宏对位数进行掩码处理,并通过文档和类型长度检查进行明确规定。
优点:
缺点: