0

I have the following questions:

1)

    uint8_t a = 1;
    uint8_t b = 1;
    
    uint16_t res = a + (b << 8);

Does integer promotion takes place before or after the shift operation?

2)

    uint8_t a = 1;
    uint8_t b = 1;
    
    uint16_t res = b << 8;

Does integer promotion takes place here?

3) Does integer promotion takes place in all kinds of expressions (e.g. even if it's just a shift operation)?

Note: The integer width is 32 bits in my system.

Alex
  • 358
  • 1
  • 11
  • 1
    [Implicit type promotion rules](https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules). So to begin with, the question(s) cannot be answered if we don't know the size of `int` on your specific system. – Lundin Sep 24 '20 at 14:05
  • 1
    Promotion never takes account of the size of the destination. That would be really dumb (but is done in at least one, really dumb, language). – EML Sep 24 '20 at 14:09
  • Even if shifting `uint8_t` by `8` was legal it *has* to be promoted to be of use otherwise the result would always be 0. – Weather Vane Sep 24 '20 at 14:21
  • @WeatherVane Only the width of the _promoted_ left operand matters when determining too large shifts. So `u8 << 8` is always fine. If it makes sense, well that's another story. – Lundin Sep 24 '20 at 14:25
  • @EML which language is that? – phuclv Sep 24 '20 at 15:03
  • @phuclv: Verilog... – EML Sep 24 '20 at 16:33

2 Answers2

3

Implicit type promotion rules answer most of these questions.

Assuming 32 bit int, then:

1). Integer promotion in the expression a + (b << 8); happens twice.

  • First b is promoted to int (which is a signed type, potentially dangerous for shifting!)
  • 8 is already int or it would have been promoted too.
  • The shift operators specifically have a special rule saying that the result has the type of the (possibly promoted) left operand. int in this case.
  • Then when the + operator is used, the usual arithmetic conversions are performed. As part of those, a is integer promoted to int. The other operand, result of shift, is already int. So the result of + will be of type int.
  • Conversion upon assignment converts the int to uint16_t.

2). Yes, b is integer promoted to int, shifted, and then converted to uint16_t. Just like in 1) really.

3). It depends on the operators involved. It happens in most cases of arithmetic, assuming the operands are small integer types. But there are a lot of special case operators like sizeof, unary * etc which don't promote the operand(s), for natural reasons. And other cases like assignment or function calls that have their own specialized promotion rules.

Lundin
  • 195,001
  • 40
  • 254
  • 396
1
  1. uint16_t res = a + (b << 8);

C 2018 6.5.7 covers <<. Paragraph 3 says the integer promotions are performed on both operands. So the uint8_t b is promoted to int. 8 is already an int, so the integer promotions technically occur but have no effect.

6.5.6 covers binary +. For arithmetic operands, paragraph 4 says the usual arithmetic conversions are performed on the operands (jointly). When both operands are integers, the usual arithmetic conversions include the integer promotions on both operands, per 6.3.1.8 1. So the uint8_t a is promoted to int. Note that in the semantics of the C standard, this is not sequenced relative to the shift; it can occur, at least conceptually, either before or after the shift. The integer promotions are also performed on the right operand of +, (b << 8). These again have no effect, but they do occur conceptually after the shift.

  1. uint16_t res = b << 8;

Yes, the integer promotions are applied to b and 8, as above.

  1. Does integer promotion takes place in all kinds of expressions (e.g. even if it's just a shift operation)?

No. The integer promotions are not performed on operands that do not have integer type (such as pointers for floating-point types) and are not included in:

  • Parentheses.
  • Array subscripting.
  • Arguments to functions with prototypes, for arguments matching typed parameters (not those matching ... in the function declaration).
  • Prefix and postfix ++ and --.
  • Unary &.
  • size and _Alignof.
  • Casts.
  • + and - where one operand is a pointer.
  • && and ||.
  • The first operand of ? :.
  • Simple assignment.
  • The comma operator.
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312