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

C语言无符号整数右移问题:~0直接右移时空位未补0?

问题根源:类型与整数右移规则的差异

这个问题的核心其实是C语言中整数类型的默认规则有符号/无符号右移行为的区别,咱们一步步拆解:

1. 先搞懂~0到底是什么

在C里,0默认是int类型(有符号整数)。~是按位取反操作,对int的每一位取反后,得到的是全1的有符号整数——也就是补码表示的-1(因为int的最高位是符号位,全1的补码对应十进制-1)。

当你用%u(无符号格式符)打印它时,C会把这个有符号的-1转换成无符号整数,结果就是unsigned int的最大值4294967295,但注意:此时~0本身的类型还是int,只是打印时被转换了

2. 直接对~0右移为什么结果不变?

因为~0int类型(有符号),C语言对有符号整数的右移采用算术右移:右侧丢弃低位,左侧填充符号位(也就是最高位的值,这里是1)。

所以~0 >> 2其实是对有符号的-1做算术右移2位,结果还是全1的int(也就是-1),用%u打印出来自然还是4294967295,看起来和原数一样。

3. 存入unsigned int变量后右移正常的原因

当你把~0(int类型的-1)赋值给unsigned int temp时,触发了类型转换:有符号整数-1会被转换成无符号整数,规则是加上2^N(N是无符号类型的位数,这里32位就是2^32),结果就是4294967295,此时temp的类型是无符号整数

无符号整数的右移是逻辑右移:右侧丢弃低位,左侧填充0。所以temp >> 2就是把全1的无符号数右移2位,高位补0,结果就是1073741823,这和你预期的一致。

4. 左移为什么两种方式都正常?

不管是有符号还是无符号整数的左移,规则都是统一的:左侧丢弃高位,右侧填充0。所以不管是直接对~0(int的-1)左移,还是存入无符号变量后左移,结果都是把全1的二进制左移2位(丢弃最高两位,右侧补0),转换成无符号打印时结果一致,所以看起来都正常。

验证小技巧

如果想直接对~0做右移得到预期结果,你可以强制转换类型,比如:

printf("%u \n", (unsigned int)~0 >> 2);

这样就会先把~0转换成无符号整数,再做逻辑右移,结果就是1073741823

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

火山引擎 最新活动