6

Why does -fsanitize=undefined throw

runtime error: left shift of 1 by 31 places cannot be represented in type 'int'

on this code

uint32_t z;
z = 1 << 31;

?

user7610
  • 25,267
  • 15
  • 124
  • 150
Geremia
  • 4,745
  • 37
  • 43
  • 9
    Shifting into (or beyond) the sign bit is undefined behavior. While `z` is `uint32_t`, `1` is a plain old `int`, which is signed (and not necessarily 32 bits wide). – Adrian McCarthy Dec 01 '18 at 00:14

2 Answers2

9

Make the 1 unsigned:

uint32_t z;
z = UINT32_C(1) << 31;
Geremia
  • 4,745
  • 37
  • 43
  • 4
    That's not guaranteed to work. `1u` is of type `unsigned int`, which is not guaranteed to be wider than 16 bits. You say you need to cast it, but then you don't cast it. You can do `unsigned uint32_t z = (uint32_t)1 << 31;` – Keith Thompson Dec 01 '18 at 02:38
  • 1
    Better to use a constant literal of the correct type than cast: `UINT32_C(1) << 31` – Chris Dodd Dec 01 '18 at 03:26
  • @ChrisDodd What issues could casting present? – Geremia Dec 01 '18 at 16:38
  • 1
    The cast will be constant-folded away so has no extra cost (except when optimization is completely disabled), but occasionally causes precedence confusion. Using `static_cast<`.. can avoid the latter, but is C++ only and more verbose. The constant literal ensures that it is really constant. – Chris Dodd Dec 02 '18 at 02:47
5

Because a left shift of 1 by 31 places cannot be represented in type int.

Mathematically, 1 << 31 is 231, or 2147483648. INT_MAX on a typical system (where int is 32 bits) is one less than that, or 2147483647. If an arithmetic operation on a signed type overflows (yields a result outside the result of the type), the behavior is undefined. (Don't assume it will wrap around. It might, but the language doesn't guarantee it.)

If you need a type that can represent that value, you can use an unsigned type that's at least 32 bits wide, or a signed type that's more than 32 bits wide. unsigned long or long long is guaranteed to be that wide. (The language doesn't guarantee that int is more than 16 bits wide, but it's likely to be 32 on most systems.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631