这是编译输出让我哭的程序:
#include <inttypes.h>
int main()
{
uint32_t limit = (1 << 32) - 1; // 2^32 - 1 right?
}
这是编译输出:
~/workspace/CCode$ gcc uint32.c
uint32.c: In function ‘main’:
uint32.c:5:29: warning: left shift count >= width of type [-Wshift-count-overflow]
uint32_t limit = (1 << 32) - 1; // 2^32 - 1 right?
我认为(1 << 32) - 1
等于2 ^ 32 - 1,32位无符号整数的范围是0到2 ^ 32 - 1,不是这样的吗?我哪里出错了?
答案 0 :(得分:4)
警告是正确的,32位数中的最高位是第31位(0索引),因此溢出前的最大位移是1 << 30
(由于符号位,因此为30)。即使您在某个时刻执行-1
,也必须存储1 << 32
的结果,并将其存储在int
中(在这种情况下恰好是32位)。因此你得到了警告。
如果你真的需要获得32 bit unsigned int
的最大值,你应该以简洁的方式做到:
#include <stdint.h>
uint32_t limit = UINT32_MAX;
答案 1 :(得分:3)
您有两个错误:
1
属于int
类型,因此您将初始值计算为int
,而不是uint32_t
。1 << 32
为32位或更少,则int
为 未定义的行为 。 (uint32_t)1 << 32
也将是未定义的。(另请注意,如果1 << 31
为32位,由于溢出,int
也将是未定义的行为)
由于算术以模2^32
为模,因此更简单的方法就是
uint32_t x = -1;
uint32_t y = (uint32_t)0 - 1; // this way avoids compiler warnings
答案 2 :(得分:1)
在尝试计算目标常量时,编译器在示例中使用int。想象一下,编译器没有任何可用的优化,并且为您的班次生成汇编程序。对于32位int shift指令,数字32将变大。
此外,如果要设置所有位,请使用~0