Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C guarantee 32-bit integer arithmetic?

Tags:

c

In C, suppose int is 32 bit,

uint64_t x = 1000000u * 1000000u;

this is commonly implemented by multiplying the numbers for a 32-bit result, discarding overflow bits, then assigning with zero extension to x.

Does the language guarantee this, or could the compiler instead choose to do everything in 64 bits, giving the mathematically accurate result?

(I know the language standard allows int to be 64 bit in the first place. I'm talking specifically about the situation where int is 32 bit.)

like image 299
rwallace Avatar asked Dec 07 '22 11:12

rwallace


1 Answers

uint64_t x = 1000000u * 1000000u;

Your stated assumption is that int is 32 bits. To be 100% clear, we need to assume that UINT_MAX is 232-1, or 4294967295. (The standard requires unsigned int to have a range of at least 0 to 65535, which implies a size of at least 16 bits -- but it can have padding bits.) It's almost certainly the same thing (I don't know of any C implementations that have padding bits), but we should be explicit if we want to ask what the standard guarantees.

Given that assumption, the constant 1000000u is of type unsigned int, and the result of the multiplication is 3567587328u, also of type unsigned int. That value is converted to uint64_t (with no loss of information) and stored in x.

uint64_t is guaranteed to be exactly 64 bits wide with no padding bits. An implementation that doesn't have a type that satisfies those conditions will not define uint64_t, so the above wouldn't compile. (I'm assuming, of course, that this refers to the uint64_t defined in the standard <stdint.h> or <inttypes.h> header.)

The general rule for arithmetic expressions is that the type of an expression is determined by the types of its operands, not by the values of its operands or the context in which it appears. If we drop the assumption about the upper bound of unsigned int, the constant 1000000u could be of type unsigned int or unsigned long, whichever type is big enough to hold it -- but the value of the product is the same as the type of the constants, even if that results in overflow wraparound. (Strictly speaking, unsigned operations don't overflow.)

like image 199
Keith Thompson Avatar answered Dec 22 '22 00:12

Keith Thompson