2

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
lostyzd
  • 4,515
  • 3
  • 19
  • 33

3 Answers3

12

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.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Thanks. Now I wonder why C language made `<<` different from other operators? P.S. I just lost 20$ on this. – lostyzd Jun 02 '13 at 06:20
  • 4
    Bad luck! You could have gotten a copy of the standard for only $10 more than that...which might have been a better investment. – Jonathan Leffler Jun 02 '13 at 06:21
  • 3
    @lostyzd I think because it's an asymmetrical operator, and the size of the right operand is clearly irrelevant. Only its value. – Elazar Jun 02 '13 at 06:23
  • 2
    This answer would be better if the statement that shift operators are different from most other operators in the conversion of operands were at the beginning. That aspect of the operator is what caused the most confusion or surprise, and understanding that the type of the right operand does not affect the conversion of the left operand is key. – Eric Postpischil Jun 02 '13 at 13:33
3

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?

Elazar
  • 20,415
  • 4
  • 46
  • 67
3

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.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765