5

Under GCC, the following code always return the left operand of << if num1s == 0:

0xFFFFFFFFu << (32-num1s);

After reading Why doesn't left bit-shift, "<<", for 32-bit integers work as expected when used more than 32 times?, and the standard quoted by David Heffernan, it seems that if the left operand is unsigned, it is a defined operation. It is only when E1 (the left operand) has a signed type and non-negative value that it could result in undefined behavior.

Can any one explain if the standard states explicitly that if the amount shifted is larger than the number of bits the type contains, it is undefined behavior?

Community
  • 1
  • 1
Rich
  • 1,669
  • 2
  • 19
  • 32
  • "The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand." but seriously, get yourself a copy of the standard, these questions are trivial to answer for yourself. – Marc Glisse Oct 10 '15 at 19:55
  • Why would it be an undefined behavior? It is very much defined and the operation would result in a `0`. – YePhIcK Oct 10 '15 at 19:56
  • 3
    @YePhIcK It is undefined purely because it is defined to be. – Neil Kirk Oct 10 '15 at 19:57
  • @YePhIcK It's undefined because the standard says so in very clear and unambiguous words. – n. m. could be an AI Oct 10 '15 at 20:06
  • The question this is marked as a duplicate of is for C. This question is for C++. – David Stone May 04 '21 at 02:49

2 Answers2

6

§5.8 Shift operators

The type of the result is that of the promoted left operand. The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.

The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are zero-filled. If E1 has an unsigned type, the value of the result is E1 × 2E2, reduced modulo one more than the maximum value representable in the result type. Otherwise, if E1 has a signed type and non-negative value, and E1×2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

Community
  • 1
  • 1
Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
  • Thanks for the quote from the standard. Is there a free C++ standard online somewhere? – Rich Oct 11 '15 at 07:55
  • 1
    @Rich You can obtain it [here](https://isocpp.org/std/the-standard). The finalized standard must be purchased, but you can get the draft (which is 99% the same as the final version) for free on that same page. – Cory Kramer Oct 11 '15 at 12:41
  • The latest draft is available as free pdf: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4849.pdf – bebbo Aug 06 '23 at 07:10
6

CoryKramer has answered why it is an undefined behavior by standard.

I'll try to expain how it works in the real situation. C++ compilers usually implement << and >> operators for 32-bit integers as assembler instructions without checking the operand range. It means that the result depends on the processor-specific implementation of the shift instructions.

For example, Intel processor specification for 32-bit SHL/SHR/SAL/SAL instructions says:

The destination operand can be a register or a memory location. The count operand can be an immediate value or register CL. The count is masked to five bits, which limits the count range to 0 to 31.

It means that a << b becomes a << (b & 0x1f) on Intel processors. So shifting by 32 bits means no shift.

But you should not rely on this information! The compiler can also optimize the code and implement the shift operator using vector instructions. In this case, the behavior is unspecified even by processor specifications.

Andrey Nasonov
  • 2,619
  • 12
  • 26
  • Note that the first processors to use the x86 architecture would use the bottom 8 bits of the shift amount to decide how many bits to shift, so if `y` was equal to 64, `x << y` would yield 0 on those processors, but `x` on newer ones. There was thus no practical way that evaluation of a compile-time constant expression `1<<64` could yield behavior consistent with `x< – supercat Jan 15 '20 at 23:34