简体   繁体   中英

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? 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). 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). 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:

#include <stdint.h>

uint32_t limit = UINT32_MAX;

Or better yet, use the c++ limits header:

#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 .
  • 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. (uint32_t)1 << 32 would be undefined as well.

(also, note that 1 << 31 would be undefined behavior as well, if int is 32 bits, because of overflow)

Since arithmetic is done modulo 2^32 anyways, an easier way to do this is just

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. Imagine that rhe compiler didn't have any optimization available and was to generate assembler for your shift. The number 32 would be to big for the 32bit int shift instruction.

Also, if you want all bits set, use ~0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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