Is left-shifting a signed integer undefined behavior in C++03?

前端 未结 2 1607
一生所求
一生所求 2020-12-17 10:53

According to C++03, 5.8/2, left-shifting is defined as follows:

The value of E1 << E2 is E1 (interpreted as a bit pattern) left-shifted E2 bit p

相关标签:
2条回答
  • 2020-12-17 10:59

    I would like to add that the rules changed in C++11.

    In C++11, signed shift left of a negative number is always undefined, even if the underlying machine defines it for values that are in range. It is not implementation-defined, it is undefined. This means that if you do this, the compiler is free to do anything it wants, including delete a bunch of your code unexpectedly. This is in contrast to signed shift right of negative numbers, which is implementation-defined, meaning that its result depends upon the machine type.

    Clang's -fsanitize=undefined mode catches attempts to shift left negative numbers.

    0 讨论(0)
  • 2020-12-17 10:59

    5.8/2 says that it interprets it as a bit-pattern, which is only implementation dependent if for some reason your implementation doesn't use 2's complement, or if your compiler second-guesses you (they don't). C++11 is more explicit, but says the same thing.

    Signed integers use what's known as 2's complement. Basically if you bit-shift a signed integer by 1, if it's positive and below 2^(bits - 2) it will work as if it were unsigned. If it is above that but positive, you will create a strange negative number that bears no relation to the original. If it is negative to begin with, you'll get possibly a negative, possibly a positive number.

    For instance, if we have an 8-bit signed integer representing -1:

    11111111 // -1
    

    If we left-shift that we end up with

    11111110 // -2
    

    However, let's say we have -120

    10001000  // -120
    

    We shall end up with

    00010000  // 16
    

    Obviously that is not correct!

    Continuing, using number 65:

    01000001  // 65
    

    Shifted left, this will become:

    10000001  // -127
    

    Which equates to -127.

    However, the number 16:

    00010000 // 16
    

    Shifted left is

    00100000 // 32
    

    As you can see, it "sometimes works, sometimes doesn't" but usually works if your number is below 2^(bits-2) and sometimes but not usually if it is above -(2^(bits-2)). That is, to shift left by 1. To shift left by 2, take another bit off. Etc.

    0 讨论(0)
提交回复
热议问题