-1

Could someone explain this behavior?

#include <iostream>
using namespace std;
int main(){
    for(int i = 0; i <= 32; i++){
        unsigned long test = 1u << i;
        cout << test << endl;
    }
}

outputs:

1
2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
131072
262144
524288
1048576
2097152
4194304
8388608
16777216
33554432
67108864
134217728
268435456
536870912
1073741824
2147483648
1

Which makes sense until the end. Bit shift operators shouldn't wrap, but here it appears to be doing exactly that. I imagine it's because the literal '1u' is a smaller type than an unsigned long. Using '1ul' instead makes the behavior perfectly normal, so there must be something going on with the type conversion, but I'm curious to know exactly what and why!

1 Answers1

4

If the value of the right operand for bit-wise shift is negative or is greater or equal to the number of bits in the promoted left operand, the behavior is undefined.

From https://timsong-cpp.github.io/cppwp/n3337/expr.shift#1:

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.

And there's no sense in explaining the behavior of undefined behavior, because it's undefined.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
wildturtle
  • 101
  • 2
  • Not true. See https://timsong-cpp.github.io/cppwp/n3337/expr.shift#2. The behavior is well defined for signed types. – R Sahu Feb 07 '19 at 18:19
  • @RSahu That paragraph is not an exception to the last sentence in the preceding paragraph. – molbdnilo Feb 07 '19 at 18:28
  • @Rsahu My statement was only referring to the type used in the question (unsigned long), I don't know enough to speak for signed types. Perhaps I should have been more clear. – wildturtle Feb 07 '19 at 18:29