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?
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.
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.
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:
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
.
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:
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.
User contributions licensed under CC BY-SA 3.0