C语言中移位操作的正确顺序?三段移位代码为何输出不同结果?
三段C语言移位代码的输出差异解析
咱们来逐个拆解这三段代码,看看为啥输出不一样——核心都是C语言里的整数提升和移位规则在搞事情!
代码1:b = 66 << 2 >> 8; 输出1
首先,66是C语言默认的int类型字面量,所以整个表达式66 << 2 >> 8都是在int层面完成计算的:
66 << 2:66的二进制是000...01000010,左移2位后变成000...100001000,对应十进制264;264 >> 8:因为是正数的int右移,高位补0,264右移8位后剩下000...00000001,也就是十进制1;
最后把这个int类型的1赋值给signed char b,完全在signed char的范围(-128~127)内,所以输出1。
代码2:分步移位输出0
这段代码把移位拆成了两步,中间的赋值截断是关键:
b = 66 << 2;:先计算66 << 2得到int类型的264,但要赋值给8位的signed char时,超出范围的部分会被截断——264减去256(2^8)后得到8,所以此时b的值是8;b = b >> 8;:b是signed char类型,在参与移位运算前会触发整数提升,自动转换成int类型(值还是8)。对int类型的8右移8位,高位补0后结果就是0,赋值给b后输出0。
代码3:移位位数为0输出66
这里的关键是移位位数变成了0:
b = 2 >> 8;:2是int类型,右移8位后所有有效位都被移出,结果是0,赋值给b后b的值为0;66 << b:也就是66 << 0,根据C语言规则,任何数左移0位都等于它本身,所以结果还是66,赋值给b后输出66。
核心差异总结
这三段代码的本质区别在于:
- 运算的类型阶段:代码1的两次移位都在
int上完成后再赋值;代码2是先截断到char,再以提升后的int做第二次移位; - 移位位数的有效性:代码3的移位位数为0,直接返回原数;
- 整数提升与截断:C语言中,
char/short这类小于int的类型,参与运算时会先提升为int,赋值时又会截断回原类型,这两个步骤直接左右了最终结果。
内容的提问来源于stack exchange,提问作者homior




