I've realized and read that multiplying a uint16_t
with another uint16_t
results in an integer (it actually seems to be a signed integer? see: ). Given that, do I have to assume that the following function f
produces undefined behavior, because there'll be a signed integer overflow?
The overflow would occur, because x*x
for x=45000
results in "almost" INT32_MAX
and it will then overflow if it is multiplied again by x
.
(btw: on my platform int
is a int32_t
)
#include <stdio.h>
#include <stdint.h>
uint16_t f(uint16_t x) {
printf("%zu\n", sizeof(x)); // <-- 2
printf("%zu\n", sizeof(x * x)); // <-- 4
return x * x * x;
}
int main()
{
uint16_t x = 45000;
uint16_t y = f(x);
}
The overflow would occur, because x*x
for x=45000
results in "almost" INT32_MAX
and it will then overflow if it is multiplied again by x
.
Is this correct, or do I make some wrong assumptions?
You are correct that your posted code will invoke undefined behavior due to signed integer overflow.
According to §6.3.1.1 ¶2 of the ISO C11 standard, the uint16_t
operands will both get promoted to an int
, because an int
is 32-bits wide on your platform and therefore able to represent all values representable by uint16_t
. If this were not the case, then the operands would get promoted to unsigned int
.
Therefore, on platforms on which int
is 32 bits wide, you will be getting a signed integer overflow (which is undefined behavior), whereas on platforms on which int
is 16 bits wide, you will be getting an unsigned integer overflow (which is not undefined behavior).