C学习:无符号有符号数的移位问题分析总结

C学习:无符号有符号数的移位问题分析总结

移位原则


重要重要重要:对于有符号数来说,移位操作在C语言标准中行为未定义,不同平台不一样,取决于编译器类型。无符号数统一按逻辑移位实现,行为确定。

虽然一般编译器中有符号位数移位都是按照算术移位实现的,但还是建议仅对无符号数进行位运算,且移位过程中的右操作数必须为非负数,若为负数也是未定义行为。更多细节见《C程序设计语言》中2.9按位运算符解析。

移位分析


首先,理清几个概念:

  • 逻辑移位:移位时空置填零,主要针对无符号数移位场景
    • 右移时,移出的丢弃,空位填零;左移时,最高位移动,如果是符号位,可能会变正负。
  • 算术移位:移位时带符号位,主要针对有符号数移位场景;有时也叫符号移位。
    • 右移时,移出的丢弃,空位填符号位;左移时,符号位不动,只移动数据,末尾填零。

在这里插入图片描述

引用自参考资料1:C语言中无符号数和有符号数的左移和右

无符号数移位统一按逻辑移位,空位补零,超过位宽抛弃。

有符号数移位由编译器决定,可能按算术移位,也可能按逻辑移位。

总之,避免有符号数移位操作

  • 编码规范中要求避免对带符号数右移的一个重要理由是:并非所有的处理器都支持算术右移(即:在右移时对高位做符号位扩展)。
  • 所以在C标准中将对负数右移的行为定义为“implementation-defined”,由 编译器自定义
  • 目前测试所知,ARM和x86平台可以正确处理带符号数移位情况,即是按算术移位。

对于数据长度小于int类型的无符号整数做位操作时,编译器会隐式进行整数提升,再对提升后的整数进行位操作,因此对于这类无符号数做位操作时要特别小心,避免出现非预期的结果。

——需要注意的点

参考资料


  1. C语言中无符号数和有符号数的左移和右移,link
  2. 书籍:C程序设计语言,2.9按位运算符解析

猜你喜欢

转载自blog.csdn.net/qq_17256689/article/details/129961174