简体   繁体   English

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

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

Here is the program whose compilation output makes me cry:这是编译输出让我哭的程序:

#include <inttypes.h>

int main()
{
        uint32_t limit = (1 << 32) - 1; // 2^32 - 1 right?
}

and here is the compilation output:这是编译输出:

~/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?

I thought that (1 << 32) - 1 equals to 2^32 - 1 and that unsigned integers on 32 bits range from 0 to 2^32 - 1, isnt it the case?我认为(1 << 32) - 1等于 2^32 - 1 并且 32 位的无符号整数范围从 0 到 2^32 - 1,是不是这样? Where did I go wrong?我哪里做错了?

The warning is correct, the highest bit in a 32bit number is the 31st bit (0 indexed) so the largest shift before overflow is 1 << 30 (30 because of the sign bit).警告是正确的,32 位数字中的最高位是第 31 位(0 索引),因此溢出前的最大移位是1 << 30 (30 因为符号位)。 Even though you are doing -1 at some point the result of 1 << 32 must be stored and it will be stored in an int (which in this case happens to be 32 bits).即使您在某个时候执行-1 ,也必须存储1 << 32的结果,并将其存储在一个int (在这种情况下恰好是 32 位)。 Hence you get the warning.因此,您会收到警告。

If you really need to get the max of the 32 bit unsigned int you should do it the neat way:如果您确实需要获得32 bit unsigned int的最大值,则应该以简洁的方式进行:

#include <stdint.h>

uint32_t limit = UINT32_MAX;

Or better yet, use the c++ limits header:或者更好的是,使用 c++ 限制头文件:

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

You have two errors:你有两个错误:

  • 1 is of type int , so you are computing the initial value as an int , not as a uint32_t . 1int类型,因此您将初始值计算为int ,而不是uint32_t
  • As the warning says, shift operators must have their shift argument be less than the width of the type.正如警告所说,移位运算符的移位参数必须小于类型的宽度。 1 << 32 is undefined behavior if int is 32 bits or less.如果int为 32 位或更少,则1 << 32未定义的行为 (uint32_t)1 << 32 would be undefined as well. (uint32_t)1 << 32也将是未定义的。

(also, note that 1 << 31 would be undefined behavior as well, if int is 32 bits, because of overflow) (另外,请注意1 << 31也是未定义的行为,如果int是 32 位,因为溢出)

Since arithmetic is done modulo 2^32 anyways, an easier way to do this is just由于算术无论如何都是以2^32为模完成的,因此一种更简单的方法就是

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

The compiler is using int internally in your example when trying to calculate the target constant.尝试计算目标常量时,编译器在您的示例中内部使用 int 。 Imagine that rhe compiler didn't have any optimization available and was to generate assembler for your shift.想象一下,rhe 编译器没有任何可用的优化,而是为您的班次生成汇编程序。 The number 32 would be to big for the 32bit int shift instruction.对于 32 位 int 移位指令,数字 32 会很大。

Also, if you want all bits set, use ~0此外,如果您想设置所有位,请使用 ~0

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

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