在 C++11 标准中,为啥要依赖 char 类型的实现?

Posted

技术标签:

【中文标题】在 C++11 标准中,为啥要依赖 char 类型的实现?【英文标题】:In the C++11 standard, why leave the char type implementation dependent?在 C++11 标准中,为什么要依赖 char 类型的实现? 【发布时间】:2019-09-12 01:27:34 【问题描述】:

背景

几个 C++ 源材料和堆栈溢出问题讨论了 char 的实现依赖性质。也就是说,C++ 中的char 可以定义为unsigned charsigned char,但根据ARM Linux FAQ,此实现depends entirely on the compiler:

上面的代码实际上是错误的,因为它假定类型“char”等价于“signed char”。 C 标准确实说“char”可以是“signed char”或“unsigned char”,这取决于编译器的实现或所遵循的平台。

这为歧义问题和不良做法打开了大门,包括mistaking the signage of a char 用作 8 位数字。 Rationale for C 提供了为什么会出现这种情况的一些原因,但没有解决留下歧义可能性的问题:

指定了三种类型的 char:signed、plain 和 unsigned。一个普通的 char 可以表示为有符号或无符号,这取决于实现,如在先前的实践中一样。引入有符号字符类型是为了在那些将普通字符实现为无符号的系统上提供单字节有符号整数类型。出于对称的原因,关键字signed 被允许作为其他整数类型的类型名称的一部分。

如果只保留unsigned charsigned char 的类型作为8 位单元的两种数据类型,那么关闭甚至可能产生歧义的可能性似乎是有利的。这促使我提出这个问题......

问题

考虑到歧义的可能性,为什么要依赖 char 数据类型实现?

【问题讨论】:

char 类型在 C++ 中是一团糟。它们有 3 个完全不同的用途:字符串中的字符、字节和整数,在类型系统中无法消除它们之间的歧义。尝试cout std::int8_t ...是的... 一些处理器更喜欢有符号字符,而另一些处理器更喜欢无符号字符。例如,POWER 可以从内存中加载一个零扩展的 8 位值,但不是符号扩展。但是 SuperH-3 可以从内存中加载一个带有符号扩展但不能为零扩展的 8 位值。 C++ 派生自 C,C 保留了语言实现定义的许多细节,以便可以定制每个实现以使其最有效地适应其目标环境。 @RaymondChen 这应该是一个答案 @RaymondChen 根据 bolov 的建议,我已将您的评论作为社区 wiki 答案。 请记住,普通 charsigned charunsigned char 具有相同的表示形式,但它们仍然是三种不同且不兼容的类型。 【参考方案1】:

一些处理器更喜欢有符号字符,而另一些处理器更喜欢无符号字符。例如,POWER 可以从内存中加载一个零扩展的 8 位值,但不是符号扩展。但是 SuperH-3 可以从内存中加载一个带有符号扩展但不能为零扩展的 8 位值。 C++ 派生自 C,C 保留了语言实现定义的许多细节,以便可以定制每个实现,使其最适合其目标环境。

【讨论】:

重要的是,当您使用char 作为实际字符数据时,符号无关紧要(您的怪异 ASCII 超集的字形可以像使用正值一样容易地用负值引用)。所以在这种情况下,简单的char 使用更有效的类型就可以了。只有当您将它用于数学时,实现定义的签名才是一个问题。在这种情况下,您应该明确指定签名,或者只使用像 uint8_t/int8_t 这样的 stdint 类型来明确您依赖于数字行为,而不仅仅是存储字符。

以上是关于在 C++11 标准中,为啥要依赖 char 类型的实现?的主要内容,如果未能解决你的问题,请参考以下文章

为啥从字符串常量转换为 'char*' 在 C 中有效但在 C++ 中无效

char类型为啥只能存储0-255

C语言 把char 型 或者 整数转化成二进制 要怎么转

为啥 C 或 C++ 标准不明确将 char 定义为有符号或无符号?

char是啥类型

为啥使用short不好