关于移位运算符对无符号数的影响及等价运算的技术问询
关于无符号整数移位与等价运算的解答
嘿,咱们来逐个拆解这两个问题,都是底层编程里常碰到的实用知识点:
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^31,n=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




