简体   繁体   中英

C: Undefined behavior when multiplying uint16_t?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM