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?
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
orunsigned int
may be used
- An object or expression with an integer type (other than
int
orunsigned int
) whose integer conversion rank is less than or equal to the rank ofint
andunsigned int
.- A bit-field of type
_Bool
,int
,signed int
,orunsigned 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 anint
; otherwise, it is converted to anunsigned 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.