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?
CodePudding user response:
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).