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

文章讨论了C语言中无符号数和有符号数的移位操作。对于无符号数,移位遵循逻辑移位,空位补零;而有符号数的移位行为未定义,依赖于编译器,可能按算术移位处理。建议避免对有符号数进行移位操作,尤其是右移,因为不是所有处理器都支持算术右移。此外,对于小于int类型的数据进行位操作时需谨慎,因为可能涉及整数提升。

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

移位原则


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

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

移位分析


首先,理清几个概念:

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

在这里插入图片描述

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

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

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

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

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

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

——需要注意的点

参考资料


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值