lostyzd
lostyzd

Reputation: 4523

Weird integral promotions with left shift operator

Please see the code below, why no integral promotion for literal "1"?

long long n = 50;
long long a = 1 << n; // 262144
long long b = 1LL << n; // 1125899906842624

Upvotes: 2

Views: 1742

Answers (3)

Jonathan Leffler
Jonathan Leffler

Reputation: 753695

As requested by elazar:

The result shown is an acceptable result because the shift invokes undefined behaviour. That's because the plain 1 is an int, and shifting an int by a value outside the range 0..(sizeof(int) * CHAR_BIT)-1 (normally, 0..31) leads to undefined behaviour.

Note that the type of a shift is affected only by the type of the (promoted) left-hand operand. This is (as chris noted at one time) different from most other binary operators, such as addition, where the types of both operands influence the type of the result. Of course, the type of an assignment is controlled by the type of the left operand and the value on the right is coerced to the correct type if necessary (but the value on the right of an assignment is calculated without reference to the type that it will be assigned to, as in this example).

ISO/IEC 9899:2011 (C)

§6.5.7 Bitwise shift operators

¶3 The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

ISO/IEC 14822:2011 (C++)

§5.8 Shift operators

The operands shall be of integral or unscoped enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand.

Upvotes: 12

AnT stands with Russia
AnT stands with Russia

Reputation: 320451

I suspect that you mixed integral promotions and usual arithmetic conversions.

Integral promotions promote smaller integral operands to int or unsigned int types. Since 1 is already an int, it cannot be promoted any further.

Usual arithmetic conversions bring operands of binary operators to common type (like it happens in case of binary +, for example), which is then used to perform the actual calculation. I suspect that you expected these conversions to occur in your example, since the right-hand operand has long long type. I.e. you probably expected your 1 to get converted to long long type as well. However, usual arithmetic conversions are simply not performed for bitwise shift operators. They are performed for additive, multiplicative, relational operators and so on, but not for bitwise operators. This is why 1 remains an int and the code triggers undefined behavior.

Upvotes: 3

Elazar
Elazar

Reputation: 21595

Here is an equivalent code:

long long n = 50;
int x = 1;
x <<= n; // sizeof(x) is 4, probably. 32 bit. we are shifting it by 50.
long long a = x;

long long z = 1LL;
z <<= n;
long long b = z;

Is it more clear now?

Upvotes: 3

Related Questions