1

Let's say we have the following code, meant to shift the bits of a to the left by i and replace the i LSBs of a with the i MSBs of b

unsigned short a;
unsigned short b;
auto i = 4;

a = (a << i) | (b >> (16 - i));

This works as expected. Now, let's consider the situation where we want to be able to do this for pairs of different types. i.e. we want to shift the bits of a to the left by i and replace the i LSBs of a with the i MSBs of b, except now we have no guarantee on the size of a and b, only that they are unsigned. Let's consider the case where the size of a is less than that of b

unsigned short a;
unsigned int b;
auto i = 4;

a = (a << i) | (b >> (32- i));

I'm worried about "overshifting" a. However, depending on when the promotion of a to unsigned int occurs, a value may or may not be an overshift. Consider a value of i=24. This would cause undefined behavior if the type conversion happens after the shift, however not before. Thus, my question is when type conversion in this case will occur? I suppose I could explicitly cast a to the larger type, but I'd like to avoid that if possible.

Throckmorton
  • 564
  • 4
  • 17

1 Answers1

1

Here's the relevant quote from the standard, [expr.shift/1]:

[...] 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. [...]

This means in your case that a will be promoted to int (or unsigned int) before doing the shift.

Note, that with current 32/64-bit compilers, the promoted type is int, not unsigned int. The promoted type is unsigned int only if int cannot represent the whole range of unsigned short (for example, this is true for old, 16-bit compilers, where sizeof(int) is 2, and sizeof(short)==sizeof(int)).

geza
  • 28,403
  • 6
  • 61
  • 135