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).
do I have to assume that the following function f produces undefined behavior, because there'll be a signed integer overflow?
Yes, on 32-bit int/unsigned
implementations. No signed integer overflow on 16-bit int/unsigned
ones.
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.
Yes and int
overflow is undefined behavior (UB).
To avoid int
overflow UB, use unsigned
math and let the compiler emit efficient code. Works well for int/unsigned
as 16, 32, ... bit widths.
// return x * x * x;
return 1u * x * x * x; // Coerce into using unsigned math
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.