[英]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();
你有两个错误:
1
是int
类型,因此您将初始值计算为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.