Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is uint8_t ≠ unsigned char?

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.)

like image 423
user541686 Avatar asked Apr 22 '13 01:04

user541686


People also ask

Is uint8_t always unsigned char?

If it exists, uint8_t must always have the same width as unsigned 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 as unsigned char ; for instance, the bits could be interpreted in the opposite order.

Is uint8_t same as unsigned char?

uint8_t always matches range and size of unsigned char and padding (none) when unsigned char is 8-bit. When unsigned char is not 8-bit, uint8_t does not exist.

Is uint8_t signed?

uint8_t and int8_t are optional integer types of exactly 8 bits. Both types have no padding, and int8_t uses 2's complement. uint8_t is unsigned, and has the range zero to UINT8_MAX , which is [0, +255]. int8_t is signed, and has the range INT8_MIN to INT8_MAX , which is [−128, +127].

Should I use char or uint8_t?

If the intended use of the variable is to hold an unsigned numerical value, use uint8_t; If the intended use of the variable is to hold a signed numerical value, use int8_t; If the intended use of the variable is to hold a printable character, use char.


2 Answers

If it exists, uint8_t must always have the same width as unsigned 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 as unsigned char; for instance, the bits could be interpreted in the opposite order. This is a silly example, but it makes more sense for int8_t, where signed char might be ones complement or sign-magnitude while int8_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 the restrict keyword has been applied well. However, even if uint8_t has the exact same size and representation as unsigned 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 types uint8_t and int, for example, can never alias.

like image 81
R.. GitHub STOP HELPING ICE Avatar answered Sep 21 '22 07:09

R.. GitHub STOP HELPING ICE


On what kind of a system can uint8_t be legally defined to be a type other than unsigned char?

In summary, uint8_t can only be legally defined on systems where CHAR_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, and uint8_t can't have padding bits; it can only exist when the smallest addressable unit is exactly 8 bits wide. Providing CHAR_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:

5.2.4.2.1 Sizes of integer types 1 The values given below shall be replaced by constant expressions suitable for use in #if preprocessing directives. ... Their implementation-defined values shall be equal or greater in magnitude (absolute value) to those shown, with the same sign.

-- number of bits for smallest object that is not a bit-field (byte)    CHAR_BIT                                            8 

Thus the smallest objects must contain exactly CHAR_BIT bits.


6.5.3.4 The sizeof and _Alignof operators

...

4 When sizeof is applied to an operand that has type char, unsigned char, or signed char, (or a qualified version thereof) the result is 1. ...

Thus, those are (some of) the smallest addressable units. Obviously int8_t and uint8_t may also be considered smallest addressable units, providing they exist.

7.20.1.1 Exact-width integer types

1 The typedef name intN_t designates a signed integer type with width N, no padding bits, and a two’s complement representation. Thus, int8_t denotes such a signed integer type with a width of exactly 8 bits.

2 The typedef name uintN_t designates an unsigned integer type with width N and no padding bits. Thus, uint24_t denotes such an unsigned integer type with a width of exactly 24 bits.

3 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.

The emphasis on "These types are optional" is mine. I hope this was helpful :)

like image 34
autistic Avatar answered Sep 21 '22 07:09

autistic