The C standard specifies that integer operands smaller than int
will be promoted to int
before any arithmetic operations are performed upon them. As a consequence, operations upon two unsigned values which are smaller than int
will be performed with signed rather than unsigned math. In cases where it is important to ensure that operation on 32-bit operands will be performed using unsigned math (e.g. multiplying two numbers whose product could exceed 2⁶³) will use of the type uint_fast32_t
be guaranteed by any standard to yield unsigned semantics without any Undefined Behavior? If not, is there any other unsigned type which is guaranteed to be at least 32 bits and at least as large as int
?
No, it's not. In any case, I would advise against using the [u]int_fastN_t
types at all. On real-world systems they're misdefined; for example, uint_fast32_t
is usually defined as a 64-bit type on x86_64, despite 64-bit operations being at best (addition, subtraction, logical ops) identical speed to 32-bit ones and at worst much slower (division, and loads/stores since you use twice as many cache lines).
The C standard only requires int
to be at least 16 bits and places no upper bound on its width, so uint_fast32_t
could be narrower than int
, or the same width, or wider.
For example, a conforming implementation could make int
64 bits and uint_fast32_t
a typedef for a 32-bit unsigned short
. Or, conversely, int
could be 16 bits and uint_fast32_t
, as the name implies, must be at least 32 bits.
One interesting consequence is that this:
uint_fast32_t x = UINT_FAST32_MAX;
uint_fast32_t y = UINT_FAST32_MAX;
x * y;
could overflow, resulting in undefined behavior. For example, if short
is 32 bits and int
is 64 bits, then uint_fast32_t
could be a typedef for unsigned short
, which would promote to signed int before being multiplied; the result, which is nearly 264, is too big to be represented as an int
.
POSIX requires int
and unsigned int
to be at least 32 bits, but the answer to your question doesn't change even for POSIX-compliant implementations. uint_fast32_t
and int
could still be either 32 and 64 bits respectively, or 64 and 32 bits. (The latter would imply that a 64-bit type is faster than int
, which is odd given that int
is supposed to have the "natural size suggested by the architecture", but it's permitted.)
In practice, most compiler implementers will tend to try to cover 8, 16, 32, and 64-bit integers with the predefined types, which is possible only of int
is no wider than 32 bits. The only compilers I've seen that don't follow this were for Cray vector machines. (Extended integer types could work around this, but I haven't seen a compiler that takes advantage of that.)
If not, is there any other unsigned type which is guaranteed to be at least 32 bits and at least as large as
int
?
Yes, unsigned long
(and unsigned long long
which is at least 64 bits.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With