繁体   English   中英

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

[英]2^32 - 1 not part of uint32_t?

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

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

警告是正确的,32 位数字中的最高位是第 31 位(0 索引),因此溢出前的最大移位是1 << 30 (30 因为符号位)。 即使您在某个时候执行-1 ,也必须存储1 << 32的结果,并将其存储在一个int (在这种情况下恰好是 32 位)。 因此,您会收到警告。

如果您确实需要获得32 bit unsigned int的最大值,则应该以简洁的方式进行:

#include <stdint.h>

uint32_t limit = UINT32_MAX;

或者更好的是,使用 c++ 限制头文件:

#include <limits>
auto limit = std::numeric_limits<uint32_t>::max();

你有两个错误:

  • 1int类型,因此您将初始值计算为int ,而不是uint32_t
  • 正如警告所说,移位运算符的移位参数必须小于类型的宽度。 如果int为 32 位或更少,则1 << 32未定义的行为 (uint32_t)1 << 32也将是未定义的。

(另外,请注意1 << 31也是未定义的行为,如果int是 32 位,因为溢出)

由于算术无论如何都是以2^32为模完成的,因此一种更简单的方法就是

uint32_t x = -1;
uint32_t y = (uint32_t)0 - 1; // this way avoids compiler warnings

尝试计算目标常量时,编译器在您的示例中内部使用 int 。 想象一下,rhe 编译器没有任何可用的优化,而是为您的班次生成汇编程序。 对于 32 位 int 移位指令,数字 32 会很大。

此外,如果您想设置所有位,请使用 ~0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM