什么时候uint8_t≠unsigned char?

Meh*_*dad 59 c c++ types unsigned-char uint8t

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

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

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

R..*_*R.. 57

如果存在,则uint8_t必须始终具有相同的宽度unsigned char.但是,它不一定是同一类型; 它可能是一个独特的扩展整数类型.它也不需要具有相同的表示unsigned char; 例如,可以以相反的顺序解释比特.这是一个愚蠢的例子,但它更有意义int8_t,signed char可能是补充或符号幅度,而int8_t需要两个补码.

使用非char扩展整数类型uint8_t甚至在"普通"系统上的另一个"优点" 是C的别名规则.允许字符类型别名,这可以防止编译器大量优化使用字符指针和指向其他类型的指针的函数,除非restrict关键字已经很好地应用.然而,即使uint8_t具有完全相同的大小和表示形式unsigned char,如果实现做了它独特的,非字符类型,别名规则并不适用于它,编译器可以假设的类型的对象uint8_tint,例如,可以从不别名.

  • 在2003±2(现在不打算在邮件档案中进行挖掘)中,GCC团队考虑准确地制作`[u] int8_t`特殊扩展整数类型,以便可以更积极地优化...但最终被拒绝这个概念的理由是程序员很可能期望它们具有与`char`相同的特殊别名属性.(这几乎与我们内核人员在基于类型的别名分析*时所引起的尖叫一样*,所以我们都有点怯懦.) (21认同)
  • `typedef __uint8_t uint8_t;`是一个typedef. (11认同)
  • 为了幽默,也许一个实现可能决定与它的命名约定一致,并且与"long long"相反,它可能会引入一个"短暂的短".因此,`typedef short short int8_t;`... (3认同)
  • @Zack:感谢有趣的历史记录.如果gcc仍然提供这些类型,但默认情况下不使用它们会很好,因此功能测试宏或类似功能可以切换到它们,从而实现更积极的优化. (3认同)
  • 实际上,GCC bugzilla 中讨论了将 `uint8_t` 与字符类型分离:请参阅 <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66110>。 (2认同)

aut*_*tic 30

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

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

详细说明,CHAR_BIT定义最小可寻址单元的宽度,uint8_t不能有填充位; 它只能在最小可寻址单元正好为8位宽时存在.提供CHAR_BIT为8,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
Run Code Online (Sandbox Code Playgroud)

因此,最小的对象必须包含精确的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名称.

强调" 这些类型是可选的 "是我的.我希望这可以帮到你 :)

  • 除了宽度之外,`char`和`int8_t`之间存在细微差别.`char`可以使用1的补码,2的补码或符号和幅度表示,其中`int8_t`需要使用2的补码表示. (13认同)
  • 它与`unsigned char`不同.保证存在`unsigned char`,但只有当`CHAR_BIT == 8`时才保证为8位.`uint8_t`不保证存在,但保证为8位. (4认同)
  • 我一直认为所有特定尺寸类型的要点都是如此,如果发生了一些奇怪的事情,事情要么继续工作,要么立即打破并告诉你.当你不使用`char`s时,它们的可读性也更高. (4认同)
  • @Mehrdad我想在你真正需要`int8`的情况下,当`CHAR_BIT> 8`时它根本不会编译,因为`int8_t`甚至不存在.然而,如果使用`char`和`CHAR_BIT> 8`,那么你可能会得到一个半破坏的构建. (3认同)

zwo*_*wol 6

迄今为止没有人提到的可能性:if CHAR_BIT==8和unqualified char是无符号的,它在某些ABI中,那么uint8_t可能是typedef char而不是unsigned char.这至少在影响过载选择(及其邪恶的双胞胎,名称修改)的情况下是重要的,即如果你同时拥有两个foo(char)并且foo(unsigned char)在范围内,foo使用类型的参数调用uint8_t将更喜欢foo(char)这样的系统.

  • @LucDanton `char` 不是 *extended* 整数类型。 (2认同)
  • "它不一定是同一类型"是相关部分.我把剩下的作为一个例子. (2认同)