On 2026-03-14 Paul Eggert wrote:
> On 2026-03-14 05:04, Bruno Haible wrote:
>
> > here, clearly, everyone
> > is assuming that
> > uint8_t == 'unsigned char' has 8 bits,
> > uint16_t == 'unsigned short' has 16 bits,
> > uint32_t == 'unsigned int' has 32 bits,
> > uint64_t == 'unsigned long long' has 64 bits,
> > and two's complement.
>
> That depends on what is meant by "here". Yes, in parts of Gnulib we
> assume that. However, stdbit.in.h doesn't assume that anywhere, not
> even in the byteswap.in.h that it sometimes includes. The only place
> those types appear is in a stdbit.in.h comment. Come to think of it,
> that comment's types should be changed to match the code; done in the
> first attached patch.
It's just a comment, but if a platform exist where CHAR_BIT == 8 and
uint16_t is missing, then uint_least16_t has padding bits and
sizeof(uint_least16_t) > 2. Then the memcpy method doesn't initialize
the variable fully because it only copies two octets:
- uint16_t
+ uint_least16_t
load16_e (const unsigned char ptr[2])
{
- uint16_t value;
+ uint_least16_t value;
memcpy (&value, ptr, 2);
return value;
}
But it obviously shouldn't copy more than 2 either. It seems that the
memcpy method isn't usable in this case, and ideally the code would
fail to compile.
If CHAR_BIT == 8 and uint_least16_t has no padding bits, then
sizeof(uint_least16_t) == 2. When a 16-bit wide unsigned type with no
padding bits exists, then uint16_t must exist too (C99 7.18.1.1p3 or
C23 7.22.1.1p3).
Thus, if the memcpy examples used exact-width types for "value", then
the code would compile if CHAR_BIT == 8 && sizeof(uint_least16_t) == 2,
and otherwise fail to compile. The return type can still be a _leastN_t.
--
Lasse Collin