What is the type promotion rule for a parenthesized sub-expression?

228 views Asked by At

Assume an integer expression comprised of multiple unsigned integral types uint16_t and uint32_t. The expression contains a parenthesized sub-expression, within which all elements are of type uint16_t.

Should the elements inside the parenthesized sub-expression be promoted to uint32_t prior to evaluating the sub-expression?

For example:

#include <stdint.h>
#include <stdio.h>

int main(void)
{
    uint16_t a16 = 0x2000;
    uint16_t b16 = 0x3000;
    uint32_t c32 = 0x00000001;
    uint32_t d32;

    // Should (a16 * b16) be evaluated to 0x06000000, or to 0x0000?
    // Should d32 be evaluated to 0x06000001, or to 0x00000001?
    d32 = c32 + (a16 * b16);

    printf("d32=0x%08x\n", d32);

    return 0;
}

Trying this in ideone online compiler suggests that a16 and b16 are promoted to uint32_t prior to the multiplication. Is this mandated by the C standard? Why not evaluate to uint16_t while inside the parentheses?

3

There are 3 answers

5
dbush On BEST ANSWER

Anytime a type smaller than int is used an an expression it is first promoted to int or unsigned int regardless of the context of the expression.

This is spelled out in section 6.3.1.1p2 of the C standard:

The following may be used in an expression wherever an int or unsigned int may be used

  • An object or expression with an integer type (other than int or unsigned int) whose integer conversion rank is less than or equal to the rank of int and unsigned int.
  • A bit-field of type _Bool, int, signed int,or unsigned int.

If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions. All other types are unchanged by the integer promotions

So in your case, a16 and b16 will both be promoted to int before being applied to any operator, assuming that int is larger than uint16_t.

Note that that this is integer promotions, which is not the same as the usual arithmetic conversions. The latter dictates how two operands of different types are converted to a common type before applying the operator.

3
Bathsheba On

All types narrower than int are promoted to an int prior to the multiplication.

So if you have a 32 bit 2's complement int then the result is effectively a product of two int32_t types.

The parentheses in your expression have no effect on either this implicit type conversion, or the final result.

2
John Bollinger On

Assume an integer expression comprised of multiple unsigned integral types uint16_t and uint32_t. The expression contains a parenthesized sub-expression, within which all elements are of type uint16_t.

Should the elements inside the parenthesized sub-expression be promoted to uint32_t prior to evaluating the sub-expression?

No. There are two main possibilities:

  1. uint16_t is the same type as unsigned int. In this case, no promotions are performed in evaluating operations with two uint16_t operands, and the result has type uint16_t.

  2. int is wider than uint16_t, and can therefore represent all the values representable by uint16_t. In this case, when both operands of a binary operator have type uint16_t, both are promoted to int (which is definitely not the same as uint32_t), and the result of the operation has type int.

In principle, C does not exclude a third possibility that in practice you will never see:

  1. uint16_t is not the same type as unsigned int, but is the same size. In this case you will either have promotion to unsigned int (which cannot be the same as uint32_t in this case) or no promotion.

Under no circumstance permitted to a conforming C implementation will the operands in question be promoted to uint32_t, nor will the operations with two uint16_t operands yield a uint32_t result.