C语言中带等号与无等号的位位移结果为何不同?01与02案例差异原因?
关于C语言位位移操作的两个疑问解答
先把你的代码贴出来方便对照分析:
char c=0xAB; printf("01:%x\n", c<<2); // 输出fffffeac printf("02:%x\n", c<<=2); // 输出ffffffac printf("03:%x\n", c<<=2);
疑问一:带等号和不带等号的位位移结果不同?
这核心是整数提升规则和赋值截断行为在起作用:
- 当你用
c<<2时,c是char类型(默认带符号),在表达式里会自动提升为int类型。0xAB作为有符号char是负数(最高位为1),提升成int后会做符号扩展,变成32位的0xFFFFFFAB。对这个完整的32位值左移2位,得到的就是0xFFFFFEAC,也就是你看到的01的输出。 - 而
c<<=2是复合赋值操作,它会先执行左移,但结果会被强制截断回char的8位长度(因为c的类型是char)。0xAB左移2位后超出8位的部分直接丢掉,剩下的是0xAC,然后把这个值赋值给c。当printf输出时,c再次被提升为int,0xAC作为有符号char是负数,符号扩展后就是0xFFFFFFAC,这就是02的输出。
疑问二:01和02案例的输出差异?
本质就是两个操作的计算逻辑完全不同:
- 01是先把char提升为int,再在32位范围内左移,全程没有截断,结果保留了完整的32位数值。
- 02是先对8位的char做左移,截断后赋值给c,再把c提升为int输出,左移后的结果被砍成8位,再扩展成32位int,自然和01的结果不一样。
顺便提一句,03的输出会是0xFFFFFF28——此时c已经是0xAC,再左移2位截断成8位是0x28,扩展成int后就是这个结果啦。
内容的提问来源于stack exchange,提问作者nonamer
相关产品推荐
相关产品推荐

