2 ^ 32 - 1不是uint32_t的一部分?

时间:2016-05-25 22:50:27

标签: c uint32

这是编译输出让我哭的程序:

#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,不是这样的吗?我哪里出错了?

3 个答案:

答案 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