According to C and C++, CHAR_BIT >= 8
.
But whenever CHAR_BIT > 8
, uint8_t
can't even be represented as 8 bits.
It must be larger, because CHAR_BIT
is the minimum number of bits for any data type on the system.
On what kind of a system can uint8_t
be legally defined to be a type other than unsigned char
?
(If the answer is different for C and C++ then I'd like to know both.)
If it exists,
uint8_t
must always have the same width asunsigned char
. However, it need not be the same type; it may be a distinct extended integer type. It also need not have the same representation asunsigned char
; for instance, the bits could be interpreted in the opposite order. This is a silly example, but it makes more sense forint8_t
, wheresigned char
might be ones complement or sign-magnitude whileint8_t
is required to be twos complement.One further "advantage" of using a non-char extended integer type for
uint8_t
even on "normal" systems is C's aliasing rules. Character types are allowed to alias anything, which prevents the compiler from heavily optimizing functions that use both character pointers and pointers to other types, unless therestrict
keyword has been applied well. However, even ifuint8_t
has the exact same size and representation asunsigned char
, if the implementation made it a distinct, non-character type, the aliasing rules would not apply to it, and the compiler could assume that objects of typesuint8_t
andint
, for example, can never alias.In summary,
uint8_t
can only be legally defined on systems whereCHAR_BIT
is 8. It's an addressable unit with exactly 8 value bits and no padding bits.In detail,
CHAR_BIT
defines the width of the smallest addressable units, anduint8_t
can't have padding bits; it can only exist when the smallest addressable unit is exactly 8 bits wide. ProvidingCHAR_BIT
is 8,uint8_t
can be defined by a type definition for any 8-bit unsigned integer type that has no padding bits.Here's what the C11 standard draft (n1570.pdf) says:
Thus the smallest objects must contain exactly CHAR_BIT bits.
Thus, those are (some of) the smallest addressable units. Obviously
int8_t
anduint8_t
may also be considered smallest addressable units, providing they exist.The emphasis on "These types are optional" is mine. I hope this was helpful :)
A possibility that no one has so far mentioned: if
CHAR_BIT==8
and unqualifiedchar
is unsigned, which it is in some ABIs, thenuint8_t
could be a typedef forchar
instead ofunsigned char
. This matters at least insofar as it affects overload choice (and its evil twin, name mangling), i.e. if you were to have bothfoo(char)
andfoo(unsigned char)
in scope, callingfoo
with an argument of typeuint8_t
would preferfoo(char)
on such a system.