0

Here is my code

int a=2147483647; int b= a<<1; cout<<"a="<<a<<", b="<<b; 

The output I am getting is- a=214783647, b=-2

Binary representation of a is

0111 1111 1111 1111 1111 1111 1111 1111

By shifting it by 1 bit, it will change sign bit and replace LSB with 0. So, I think answer will be -ve and magnitude will be subtracted by 1 i.e -2147483646 But it is giving result as -2 . Please explain.

2

3 Answers 3

2

This is because your computer is using 2 complement for the signed value. Unsigned shifted value is 0xFFFFFFFE, which is -2 in 2 complement, not -2147483647.

Shifting is implementation defined in C.

BTW, -2147483647 is 0x80000001 on such CPU.

Sign up to request clarification or add additional context in comments.

Comments

2

[expr.shift]/1 The value of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are zero-filled. ... if E1 has a signed type and non-negative value, and E1 × 2^E2 is representable in the corresponding unsigned type of the result type, then that value, converted to the result type, is the resulting value; otherwise, the behavior is undefined.

Emphasis mine. Your program exhibits undefined behavior.


Edit: Upon closer consideration, I no longer think it's undefined behavior. 2147483647*2 does fit into unsigned int, "the corresponding unsigned type" of int. Its conversion to int is not undefined, but merely implementation-defined. It's entirely reasonable for an implementation using two's complement to define this conversion so that 2147483647*2 == -2, just reinterpreting the bit pattern, as other answers explained.

9 Comments

Note that the quoted paragraph is no longer in the C++ Standard. However, this sentence implies the same: eel.is/c++draft/expr#pre-4.sentence-1.
Upon closer examination, I no longer think it's undefined behavior. 2147483647*2 does fit into unsigned int, "the corresponding unsigned type" of int. Its conversion to int is not undefined, but merely implementation-defined. It's entirely reasonable for an implementation using two's complement to define this conversion so that 2147483647*2 == -2, just reinterpreting the bit pattern.
@DanielLangr The draft standard you cite defines left shift thusly: "The value of E1 << E2 is the unique value congruent to E1×2^E2 modulo 2^N, where N is the width of the type of the result." It so happens that -2 == 2147483647*2 modulo 2^32. So I think the draft standard actually expanded the domain of shift operator, and made the original expression well-defined.
@IgorTandetnik It did not. 2147483647 * 2 is 4294967294, which modulo 2^32 (N=32 is the width of the int type) is still 4294967294. And this number is not in the range of representable values for int.
@DanielLangr I'm not sure I follow. -2 is the unique value of int type that is congruent to 4294967294 modulo 2^32, is it not?
|
1

Well, there is a very long story behind.

Since int is a signed type, it means that the first bit is a sign and the whole system is two-complement.

so x = 0b 1111 1111 1111 1111 1111 1111 1111 0111 is x = -9 and for example x = 0b 1111 1111 1111 1111 1111 1111 1111 1111 is x = -1 and x = 0b 0000 0000 0000 0000 0000 0000 0000 0010 is 2

Learn more about Two complement.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.