Is it required that either all or none of the C fixed-width integer types to be defined?
Asked Answered
M

3

5

The specification specifies the types int8_t int16_t int32_t and int64_t (and their unsigned variants) and follows them with:

These types are optional.

In C the type char is at least 8 bits and short and int are at least 16 bits and long is at least 32 bits and long long is at least 64 bits. If they are all at least a certain width and at least as big as the smallest one, there could very well be for example an 8-bit type and a 32-bit type but no 16-bit type while satisfying those rules. As such could be 'gaps' in the fixed-width types?

By 'These types' do they mean each one individually or all of them as a whole? Could a conforming implementation define some but not all of the fixed width types? Do I have to worried about for example uint8_t being defined but not uint16_t?

Mnemosyne answered 23/5, 2023 at 3:33 Comment(1)
T
3

Is it required that either all or none of the C fixed-width integer types to be defined?

No. An implementation may have CHAR_BIT == 16 and so only defined (u)int64_t, (u)int32_t and (u)int16_t, yet not (u)int8_t.


Do I have to worried about for example uint8_t being defined but not uint16_t?

Don't worry about such unicorns.

Tunstall answered 23/5, 2023 at 4:28 Comment(2)
Still would be defined (u)int_least8_t, even for CHAR_BIT == 32, following clause 7.20.1.2, without having then any (u)int8_t. Funny enough. If I remember that right, some old(er) DSP implementation could have that setting, without any type physically smaller than 32-bit.Sinapism
@Sinapism True about (u)int_leastN_t and friends, yet those are required types (and so defined) and not part of OP's "fixed-width integer types" question - which are optionally required types (when not possible).Tunstall
O
6

stdint.h is a mandatory header for all compilers to implement, including freestanding implementations (embedded systems compilers). The C standard sorts the fixed width types into 3 categories:

  • Exact width types such as int32_t. If the compiler/system supports any of the 8, 16, 32 or 64 bit types with 2's complement and no padding bits, these types are mandatory.

    Otherwise, in case the compiler/system is wildly exotic, these types are optional - that is the text you quote but now placed in the correct context. ISO C17 says (7.20.1), emphasis mine:

    These types are optional. However, if an implementation provides integer types with widths of 8, 16, 32, or 64 bits, no padding bits, and (for the signed types) that have a two’s complement representation, it shall define the corresponding typedef names.

  • Minimum width types such as int_least32_t. These are mandatory to implement for all compilers.

  • Fastest minimum-width types such as int_fast32_t. These are mandatory to implement for all compilers.


As such could be 'gaps' in the fixed-width types?

Yeah in theory. Some exotic systems with 16 bit bytes exist (various more or less dysfunctional DSPs from TI) - these do not support int8_t so there is a "gap" there if you will. Some systems supporting 24 bit types also exist. As do 4 bit tiny microcontrollers.


By 'These types' do they mean each one individually or all of them as a whole?

Individually, as seen in the quote above. 8, 16, 32, or 64 bits.


Do I have to worried about for example uint8_t being defined but not uint16_t?

You don't need to worry about these types not being supported at all. Lack of portability to exotic/fictional/dysfunctional DSP systems is a feature not a problem. It is a huge waste of time to worry about portability to such systems. Anyone who decides to 1) use such an exotic DSP in the first place 2) decide to write C for it instead of asm which is the convention for DSPs only have themselves to blame. They can port your code, it's their problem created by them, not your problem.

If you are feeling paranoid you could add:

#include <stdio.h>
#if !defined(INT8_MIN) && (__STDC_VERSION__ <= 201710L)
  #error Your computer is too bad for this library.
#endif

NOTE: The upcoming C23 standard will finally drop support for exotic and fictional systems. All integers must use 2's complement, including all of the 3 categories above. (Source: C23 draft n3096, 7.22.1.)

Oratory answered 23/5, 2023 at 9:6 Comment(8)
To the OP: The portability part is important here. If you haven't tested your code on a 24-bit system, it is not going to work anyway. So don't bother!Darceydarci
"All integers must use 2's complement, including all of the 3 categories above." is unclear. 2's complement is one aspect of int32_t types. The other is that CHAR_BIT is 8 (or 16, ..., some power of 2). AFAIK, C23 still allows CHAR_BIT == 9, in which case unint8_t is not possible.Tunstall
@chux-ReinstateMonica All typedefs in stdint.h do in practice correspond to one of the native/primitive data types of C and those can no longer use any other format. In theory the stdint.h types need not have such a correspondence but I have never seen a compiler which implemented them differently, including compilers for exotic systems. The term "signed integer" now means two's complement, and so it applies to int_leastn_t and int_fastn_t too. C23 still support padding bits, so exotic systems could use that, but it cannot use any other signedness format.Oratory
@Oratory It is not a question of encoding - we agree on 2's complement. (u)intN_t is also a question of char width, even if we stay with no padding. As I read C23, CHAR_BIT == 9 remains allowed and (u)intN_t are optional. Perhaps it was an old draft? IAC, once release occurs, we will know for sure.Tunstall
@chux-ReinstateMonica Draft n3096 neither says mandatory nor optional. In fact the whole whole chapter about stdint.h seems to be some sort of work in progress/editorial fiasco. It's not ready to be published that's for sure.Oratory
@chux-ReinstateMonica This appears to be the current state of affairs as implemented in C23: open-std.org/jtc1/sc22/wg14/www/docs/n2888.htmOratory
Perhaps C23 will become C24?Tunstall
@chux-ReinstateMonica At the pace which the ISO bureaucracy spins, everything is possible. Except publications in a timely manner, that is.Oratory
T
3

Is it required that either all or none of the C fixed-width integer types to be defined?

No. An implementation may have CHAR_BIT == 16 and so only defined (u)int64_t, (u)int32_t and (u)int16_t, yet not (u)int8_t.


Do I have to worried about for example uint8_t being defined but not uint16_t?

Don't worry about such unicorns.

Tunstall answered 23/5, 2023 at 4:28 Comment(2)
Still would be defined (u)int_least8_t, even for CHAR_BIT == 32, following clause 7.20.1.2, without having then any (u)int8_t. Funny enough. If I remember that right, some old(er) DSP implementation could have that setting, without any type physically smaller than 32-bit.Sinapism
@Sinapism True about (u)int_leastN_t and friends, yet those are required types (and so defined) and not part of OP's "fixed-width integer types" question - which are optionally required types (when not possible).Tunstall
S
1

Assuming you are using C99 or newer and including <stdint.h> then you should expect to be able to figure out which of the types are available using the corresponding macro: INTn_MAX, INTn_MIN and UINTn_MAX (where n is 8, 16, 32 or 64).

Scoff answered 23/5, 2023 at 3:49 Comment(6)
But is it guaranteed that either all or none of the INTn_WIDTH macros where n is 8, 16, 32 or 64 will be provided on a given implementation?Mnemosyne
C doesn't enforce a specific bit width on its natual types to allow implementations to use the one that fits better the hardware targetted, so yes, I expect that they meant them to be individually optional, and hence that is why you have a macro for each typeScoff
f your main concern is availability (although AFAIK most implementations have all those defined together) it might be better to stick with the int_leastN_t or int_fastN_t types which are already mandatory.Scoff
@user16217248 From cppreference - Fixed width integer types: "The implementation may define typedef names ... Typedef names of the form ... may only be defined if the implementation supports an integer type of that width ... Each of the macros listed in below is defined if and only if the implementation defines the corresponding typedef name.". So, yes, it could be the case that not all of them are defined.Commorancy
INTn_WIDTH only exists in C23. They are named INTn_MIN and INTn_MAX etc in C99 to C17.Oratory
@ErdalKüçük That's a bad source. The text you quote is only there in C23. In fact it isn't clear if C23 (as per n3096) will still support INTn_MIN macros or if they will be removed. They are removed from normative text in the C23 draft but still listed in an Annex. Maybe just leave C23 out of it until it is released. And quote the actual standard instead of cppreference.Oratory

© 2022 - 2024 — McMap. All rights reserved.