65

根据 C 和 C++ CHAR_BIT >= 8,.
但是无论何时CHAR_BIT > 8uint8_t甚至都不能表示为 8 位。
它必须更大,因为它CHAR_BIT是系统上任何数据类型的最小位数。

什么样的系统可以uint8_t合法地定义为除 之外的类型unsigned char

(如果 C 和 C++ 的答案不同,那么我想两者都知道。)

4

3 回答 3

64

如果存在,则uint8_t必须始终具有与 相同的宽度unsigned char。但是,它不必是同一类型;它可能是一个不同的扩展整数类型。它也不必具有与 ; 相同的表示形式unsigned char。例如,可以以相反的顺序解释这些位。这是一个愚蠢的例子,但它更有意义int8_t,其中signed char可能是一个补码或符号大小,而int8_t需要是二进制补码。

即使在“正常”系统上也使用非 char 扩展整数类型的另一个“优势”uint8_t是 C 的别名规则。字符类型可以给任何东西起别名,这可以防止编译器对同时使用字符指针和指向其他类型的指针的函数进行大量优化,除非该restrict关键字应用得很好。但是,即使uint8_t具有与 完全相同的大小和表示形式unsigned char,如果实现使其成为不同的非字符类型,则别名规则将不适用于它,并且编译器可以假设类型uint8_t和的对象int,例如,可以从不别名。

于 2013-04-22T02:17:49.963 回答
32

什么样的系统可以uint8_t合法地定义为除 之外的类型unsigned char

总之,uint8_t只能在CHAR_BIT8 的系统上合法定义。它是一个可寻址单元,具有正好 8 个值位且没有填充位。

具体来说,CHAR_BIT定义了最小可寻址单元的宽度,并且uint8_t不能有填充位;只有当最小的可寻址单元正好是 8 位宽时,它才能存在。提供CHAR_BIT8,uint8_t可以由任何没有填充位的 8 位无符号整数类型的类型定义来定义。


以下是 C11 标准草案 (n1570.pdf) 所说的:

5.2.4.2.1 整数类型的大小 1 下面给出的值应替换为适用于#if 预处理指令的常量表达式。...它们的实现定义值的大小(绝对值)应等于或大于所示的值,具有相同的符号。

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

因此,最小的对象必须恰好包含 CHAR_BIT 位。


6.5.3.4 sizeof 和 _Alignof 运算符

...

4 当 sizeof 应用于类型为 char、unsigned char 或 signed char(或其限定版本)的操作数时,结果为 1。 ...

因此,这些是(一些)最小的可寻址单元。显然int8_t并且uint8_t也可以被认为是最小的可寻址单元,前提是它们存在。

7.20.1.1 精确宽度整数类型

1 typedef 名称 intN_t 指定宽度为 N、无填充位和二进制补码表示的有符号整数类型。因此, int8_t 表示这种宽度正好为 8 位的有符号整数类型。

2 typedef 名称 uintN_t 指定宽度为 N 且无填充位的无符号整数类型。因此,uint24_t 表示这种无符号整数类型,其宽度正好为 24 位。

3这些类型是可选的。但是,如果实现提供了宽度为 8、16、32 或 64 位的整数类型,没有填充位,并且(对于有符号类型)具有二进制补码表示,则它应定义相应的 typedef 名称。

我强调“这些类型是可选的”。我希望这可以帮到你 :)

于 2013-04-22T01:54:21.283 回答
8

到目前为止没有人提到过的一种可能性:如果CHAR_BIT==8and unqualifiedchar是无符号的,它在某些 ABI 中,那么uint8_t它可能是 typedefchar而不是unsigned char. 这至少在它影响重载选择(及其邪恶的孪生兄弟,名称修改)方面很重要,即,如果您要同时拥有两者foo(char)foo(unsigned char)在范围内,那么在这样的系统上使用foo类型参数调用uint8_t会更受欢迎。foo(char)

于 2013-04-24T22:30:29.423 回答