You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

关于移位运算符对无符号数的影响及等价运算的技术问询

关于无符号整数移位与等价运算的解答

嘿,咱们来逐个拆解这两个问题,都是底层编程里常碰到的实用知识点:


1. 移位运算符对无符号数的影响?

对于无符号整数(比如C里的unsigned int),移位操作的规则非常清晰,没有有符号数的符号位困扰:

  • 左移(<<:每左移1位,所有二进制位向左移动一位,右侧空出的位用0填充。在合法移位范围内(移位位数小于类型的总位数),这等价于把数值乘以2的对应次方。举个例子:
    unsigned int a = 4; // 二进制是 100
    a << 1; // 结果是 1000,也就是 8,等于4*2^1
    
  • 右移(>>:每右移1位,所有二进制位向右移动一位,左侧空出的位同样用0填充(这和有符号数的算术右移补符号位完全不同)。这等价于对数值做向下取整的整数除法,除以2的对应次方。比如:
    unsigned int b = 5; // 二进制是 101
    b >> 1; // 结果是 10,也就是 2,等于5//2(向下取整)
    

2. 无符号整数的等价运算疑问

问题A:x << n 是否等价于x * 2ⁿ

结论是:在移位操作合法的前提下(n小于unsigned int的位数,比如32位类型的话n < 32),两者完全等价,哪怕发生溢出也一样
因为无符号整数的溢出是C标准明确定义的:溢出结果等于原结果对2^类型位数取模。而x << n本质上就是把数值左移n位,超出类型位数的高位会被丢弃,这和x * 2ⁿ取模2^类型位数的结果完全一致。比如32位unsigned int中,x = 2^31n=1

  • x <<1 结果是0(高位被丢弃)
  • x *2^1 = 2^32,对2^32取模后也是0,两者结果相同。

问题B:x * 15 是否等价于x << 4 - x

先敲个警钟:如果你真写x << 4 - x,这和x*15完全不等价!因为C语言里<<的优先级比-高,这个表达式会被解析成x << (4 - x),逻辑完全跑偏。我猜你想表达的是(x << 4) - x,咱们基于这个正确表达式来说:
是的,两者完全等价
原因很简单:15 = 16 -1 = 2^4 -1,所以x*15 = x*(16-1) = x*16 -x。而对于无符号整数,x*16就是x <<4(只要4小于类型位数,移位合法)。而且和之前的溢出情况一样,无符号整数的减法也是基于模2^类型位数的运算,哪怕x<<4的数值小于x(也就是溢出后数值变小),(x<<4)-x的结果也会和x*15取模后的结果完全一致。


内容的提问来源于stack exchange,提问作者Shabaz

火山引擎 最新活动