The problem isn't "intmax_t". The problem is "int".
If you have an ABI, you need to put an explicit size and signedness on every parameter and return value. Period. No excuses.
No "int". No "unsigned int". If I'm being really pedantic, don't even use "char".
It should be "int32_t", "uint32_t", and "uint8_t".
Every time I see objections, it's always someone who wants to use some weird 16-bit architecture. The problem is that those libraries probably won't work anyhow since nobody tests their libraries on anything other than x86 and maybe Arm. If your "int" is 16 bits, you're likely to have a broken library anyway.
Careful about that one. I believe `uint8_t` isn't required to be a character type, which has implications for type based aliasing.
The fact that every single compiler typedefs "uint8_t" and "unsigned char" and yet that isn't guaranteed by the standard is the kind of thing that just makes you want to cry.
I'm actually genuinely curious about this: people talk about the possibility of existence, but I haven't seen anybody point to an actual compiler that implements uint8_t as an extended numeric type rather than being an equivalent typedef to "unsigned char". Is there a compiler that really does this?
> The fact that every single compiler typedefs "uint8_t" and "unsigned char" [...] and yet that isn't guaranteed by the standard
They don't. The standard is right on this. It's supposed to let authors know what can be relied on portably on real C/C++ systems in use. (Targets where char is not even 8 bits might make you cry even more, but I think those are legitimately obscure now.)
> Is there a compiler that really does this?
Here's a popular one with hobbyists in 2022. The definition of uint8_t in the Arduino system header files is not "unsigned char". I have seen this definition used elsewhere too:
typedef unsigned int uint8_t __attribute__((__mode__(__QI__)));
A few tests on generated code, however, suggest that gcc treats these
exactly as signed char and unsigned char, both in how the react to
_Generic and in how the compiler handles them for alias analysis.
So, that means that there are currently zero existing compilers that treat uint8_t differently from unsigned char.
Pretty sure I remember a GCC bug that amounted to uint8_t behaving differently to unsigned char wrt aliasing. It's the sort of thing I'd expect clang to do too.
Different architectures had all manner of different "native" sizes. 8-bit micros were still relatively expensive even up through mid-1980s. The 80286, for example, was 16-bit and went away only in the early 1990s. IBM AS/400s were still 48-bits through the mid-1990s. Apple was still dealing with non-32 bit clean applications in the mid 90s. Linux running on Alpha was still cleaning up x86-isms in mid 1990s.
C99 finally introduced "stdint.h". By the mid-2000s, everything had converged to 32-bit (or 64-bit).
C11 should have deprecated "int" so that compilers could throw warnings on it. But, then, we still haven't removed K&R signatures from the C standards, so here we are.
Comments
The problem isn't "intmax_t". The problem is "int".
If you have an ABI, you need to put an explicit size and signedness on every parameter and return value. Period. No excuses.
No "int". No "unsigned int". If I'm being really pedantic, don't even use "char".
It should be "int32_t", "uint32_t", and "uint8_t".
Every time I see objections, it's always someone who wants to use some weird 16-bit architecture. The problem is that those libraries probably won't work anyhow since nobody tests their libraries on anything other than x86 and maybe Arm. If your "int" is 16 bits, you're likely to have a broken library anyway.
There are a few variable size types that make sense in an ABI. Like `size_t` and `(u)intptr_t`.
Careful about that one. I believe `uint8_t` isn't required to be a character type, which has implications for type based aliasing.
The fact that every single compiler typedefs "uint8_t" and "unsigned char" and yet that isn't guaranteed by the standard is the kind of thing that just makes you want to cry.
I'm actually genuinely curious about this: people talk about the possibility of existence, but I haven't seen anybody point to an actual compiler that implements uint8_t as an extended numeric type rather than being an equivalent typedef to "unsigned char". Is there a compiler that really does this?
> The fact that every single compiler typedefs "uint8_t" and "unsigned char" [...] and yet that isn't guaranteed by the standard
They don't. The standard is right on this. It's supposed to let authors know what can be relied on portably on real C/C++ systems in use. (Targets where char is not even 8 bits might make you cry even more, but I think those are legitimately obscure now.)
> Is there a compiler that really does this?
Here's a popular one with hobbyists in 2022. The definition of uint8_t in the Arduino system header files is not "unsigned char". I have seen this definition used elsewhere too:
https://forum.arduino.cc/t/definition-of-uint8_t/177947 https://forum.arduino.cc/t/mismatching-integer-type-definiti...Except that __attribute__((__mode__(__QI__))) makes that effectively equivalent to "unsigned char".
From https://groups.google.com/g/comp.lang.c/c/sE6I4sgGyPs
So, that means that there are currently zero existing compilers that treat uint8_t differently from unsigned char.
Pretty sure I remember a GCC bug that amounted to uint8_t behaving differently to unsigned char wrt aliasing. It's the sort of thing I'd expect clang to do too.
Personal opinion, 'int' is way above NULL as a bad idea.
"int" wasn't a bad idea "back in the day".
Different architectures had all manner of different "native" sizes. 8-bit micros were still relatively expensive even up through mid-1980s. The 80286, for example, was 16-bit and went away only in the early 1990s. IBM AS/400s were still 48-bits through the mid-1990s. Apple was still dealing with non-32 bit clean applications in the mid 90s. Linux running on Alpha was still cleaning up x86-isms in mid 1990s.
C99 finally introduced "stdint.h". By the mid-2000s, everything had converged to 32-bit (or 64-bit).
C11 should have deprecated "int" so that compilers could throw warnings on it. But, then, we still haven't removed K&R signatures from the C standards, so here we are.
IIRC K&R signatures are out in C23.