Search code examples
ctypesinteger-promotiontype-promotion

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


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?


Solution

  • 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.