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++ 限制 header:
#include <limits>
auto limit = std::numeric_limits<uint32_t>::max();
你有两个错误:
1
属于 int
类型,因此您将初始值计算为 int
,而不是 uint32_t
.
- 正如警告所说,移位运算符的移位参数必须小于类型的宽度。
1 << 32
是 未定义的行为 如果 int
是 32 位或更少。 (uint32_t)1 << 32
也将是未定义的。
(另外请注意,如果 int
是 32 位,则 1 << 31
也是未定义的行为,因为溢出)
无论如何,算术都是以 2^32
为模完成的,所以更简单的方法是
uint32_t x = -1;
uint32_t y = (uint32_t)0 - 1; // this way avoids compiler warnings
编译器在您的示例中尝试计算目标常量时在内部使用 int。想象一下,编译器没有任何可用的优化,而是为您的转变生成汇编程序。对于 32 位 int 移位指令,数字 32 太大了。
此外,如果您想要设置所有位,请使用 ~0
下面是编译输出让人哭笑不得的程序:
#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++ 限制 header:
#include <limits>
auto limit = std::numeric_limits<uint32_t>::max();
你有两个错误:
1
属于int
类型,因此您将初始值计算为int
,而不是uint32_t
.- 正如警告所说,移位运算符的移位参数必须小于类型的宽度。
1 << 32
是 未定义的行为 如果int
是 32 位或更少。(uint32_t)1 << 32
也将是未定义的。
(另外请注意,如果 int
是 32 位,则 1 << 31
也是未定义的行为,因为溢出)
无论如何,算术都是以 2^32
为模完成的,所以更简单的方法是
uint32_t x = -1;
uint32_t y = (uint32_t)0 - 1; // this way avoids compiler warnings
编译器在您的示例中尝试计算目标常量时在内部使用 int。想象一下,编译器没有任何可用的优化,而是为您的转变生成汇编程序。对于 32 位 int 移位指令,数字 32 太大了。
此外,如果您想要设置所有位,请使用 ~0