Why would uint32_t be preferred rather than uint_fast32_t?
uint32_t
is guaranteed to have nearly the same properties on any platform that supports it.1
uint_fast32_t
has very little guarantees about how it behaves on different systems in comparison.
If you switch to a platform where uint_fast32_t
has a different size, all code that uses uint_fast32_t
has to be retested and validated. All stability assumptions are going to be out the window. The entire system is going to work differently.
When writing your code, you may not even have access to a uint_fast32_t
system that isn't 32 bits in size.
uint32_t
won't work differently (see footnote).
Correctness is more important than speed. Premature correctness is thus a better plan than premature optimization.
In the event I was writing code for systems where uint_fast32_t
was 64 or more bits, I might test my code for both cases and use it. Barring both need and opportunity, doing so is a bad plan.
Finally, uint_fast32_t
when you are storing it for any length of time or number of instances can be slower than uint32
simply due to cache size issues and memory bandwidth. Todays computers are far more often memory-bound than CPU bound, and uint_fast32_t
could be faster in isolation but not after you account for memory overhead.
1 As @chux has noted in a comment, if unsigned
is larger than uint32_t
, arithmetic on uint32_t
goes through the usual integer promotions, and if not, it stays as uint32_t
. This can cause bugs. Nothing is ever perfect.
Why do many people use
uint32_t
rather thanuint32_fast_t
?
Note: Mis-named uint32_fast_t
should be uint_fast32_t
.
uint32_t
has a tighter specification than uint_fast32_t
and so makes for more consistent functionality.
uint32_t
pros:
- Various algorithms specify this type. IMO - best reason to use.
- Exact width and range known.
- Arrays of this type incur no waste.
- unsigned integer math with its overflow is more predictable.
- Closer match in range and math of other languages' 32-bit types.
- Never padded.
uint32_t
cons:
- Not always available (yet this is rare in 2018).
E.g.: Platforms lacking 8/16/32-bit integers (9/18/36-bit, others).
E.g.: Platforms using non-2's complement. old 2200
uint_fast32_t
pros:
- Always available.
This always allow all platforms, new and old, to use fast/minimum types. - "Fastest" type that support 32-bit range.
uint_fast32_t
cons:
- Range is only minimally known. Example, it could be a 64-bit type.
- Arrays of this type may be wasteful in memory.
- All answers (mine too at first), the post and comments used the wrong name
uint32_fast_t
. Looks like many just don't need and use this type. We didn't even use the right name! - Padding possible - (rare).
- In select cases, the "fastest" type may really be another type. So
uint_fast32_t
is only a 1st order approximation.
In the end, what is best depends on the coding goal. Unless coding for very wide portability or some niched performance function, use uint32_t
.
There is another issue when using these types that comes into play: their rank compared to int/unsigned
Presumably uint_fastN_t
could be the rank of unsigned
. This is not specified, but a certain and testable condition.
Thus, uintN_t
is more likely than uint_fastN_t
to be narrower the unsigned
. This means that code that uses uintN_t
math is more likely subject to integer promotions than uint_fastN_t
when concerning portability.
With this concern: portability advantage uint_fastN_t
with select math operations.
Side note about int32_t
rather than int_fast32_t
: On rare machines, INT_FAST32_MIN
may be -2,147,483,647 and not -2,147,483,648. The larger point: (u)intN_t
types are tightly specified and lead to portable code.
Why do many people use
uint32_t
rather thanuint32_fast_t
?
Silly answer:
- There is no standard type
uint32_fast_t
, the correct spelling isuint_fast32_t
.
Practical answer:
- Many people actually use
uint32_t
orint32_t
for their precise semantics, exactly 32 bits with unsigned wrap around arithmetic (uint32_t
) or 2's complement representation (int32_t
). Thexxx_fast32_t
types may be larger and thus inappropriate to store to binary files, use in packed arrays and structures, or send over a network. Furthermore, they may not even be faster.
Pragmatic answer:
- Many people just don't know (or simply don't care) about
uint_fast32_t
, as demonstrated in comments and answers, and probably assume plainunsigned int
to have the same semantics, although many current architectures still have 16-bitint
s and some rare Museum samples have other strange int sizes less than 32.
UX answer:
- Although possibly faster than
uint32_t
,uint_fast32_t
is slower to use: it takes longer to type, especially accounting for looking up spelling and semantics in the C documentation ;-)
Elegance matters, (obviously opinion based):
uint32_t
looks bad enough that many programmers prefer to define their ownu32
oruint32
type... From this perspective,uint_fast32_t
looks clumsy beyond repair. No surprise it sits on the bench with its friendsuint_least32_t
and such.