Tau*_*Tau 10 c standards type-systems integer
cppreference.com指出char
相当于
signed charorunsigned char[...],但是char是一种不同的类型,不同于signed charand两者unsigned char
我认为这意味着 a可以保存与或char完全相同的值,但与两者都不兼容。为什么决定以这种方式运作?为什么 unqualified不表示适合平台的符号,就像其他整数类型一样,其中表示与 完全相同的类型?unsigned charsigned charcharcharintsigned int
向后兼容性。大概。或者可能他们必须做出选择但并不关心。但我没有确定的答案。
\n就像OP一样,我更喜欢来自可靠来源的特定答案。如果没有这一点,合格的猜测和猜测总比没有好。
\nC 中的很多东西都来自于向后兼容性。当决定是否与实现char定义相同signed char或unsigned char由实现定义时,已经有很多 C 代码,其中一些使用有符号字符,其他使用无符号字符。强制它是其中之一肯定会破坏一些代码。
\n\n为什么不合格的字符不表示适合平台的符号的字符
\n
这并不重要。使用有符号字符的实现保证CHAR_MIN等于SCHAR_MIN且CHAR_MAX等于SCHAR_MAX。对于未签名的情况也是如此。因此,不合格的产品char将始终与其合格的对应产品具有完全相同的范围。
根据标准5.2.4.2.1p2:
\n\n\n如果在表达式中使用时,将 char 类型的对象的值视为有符号整数,则 CHAR_MIN 的值应与 SCHAR_MIN 的值相同,而 CHAR_MAX 的值应与 SCHAR_MAX 的值相同。否则,CHAR_MIN 的值应为 0,CHAR_MAX 的值应与 UCHAR_MAX 的值相同。
\n
这向我们指出,他们只是并不真正关心,或者“感觉更安全”。
\nC 标准中另一个有趣的提及是:
\n\n\n所有枚举都有一个基础类型。底层类型可以使用枚举类型说明符显式指定,并且是其固定的底层类型。如果未显式指定,则基础类型是 enumeration\xe2\x80\x99s 兼容类型,它可以是有符号或无符号整数类型(不包括位精确整数类型),也可以是
\nchar.
我正在尝试想出一个场景,在这个场景中这实际上很重要。可能导致问题的一个情况是,如果您使用一个使用有符号字符的编译器将源文件编译为共享库,然后在使用另一个使用无符号字符的编译器编译的源文件中使用该库。
\n即使这不会导致问题,想象一下共享库是用 ansi 之前的编译器编译的。嗯,我也不能肯定地说这会引起问题。但我可以想象它可以。
\nSteve Summit 在评论部分的另一个猜测:
\n\n\n我正在推测,但是:如果标准要求,用 Eric 的措辞来说,“与实现定义的选择或”
\nchar的类型相同,那么如果我所在的平台是相同的作为,我可以将两者混合在一起而不会发出警告,并创建不可移植到默认情况下未签名的计算机的代码。因此,“是与and不同的类型”的定义有助于迫使人们编写可移植的代码。signed charunsigned charcharsigned charcharcharsigned charunsigned char
但请记住,C 标准背后的人过去和现在都非常担心不破坏向后兼容性。甚至他们不想更改某些库函数的签名以返回const值,因为这会产生警告。不是错误。警告!您可以轻松禁用的警告。相反,他们只是在标准中写道,修改值是未定义的行为。您可以在这里阅读更多相关信息:https://thephd.dev/your-c-compiler-and-standard-library-will-not-help-you
因此,每当您在 C 标准中遇到非常奇怪的设计选择时,很有可能向后兼容性就是原因。这就是为什么你可以NULL用 just初始化一个指针0,即使对于 NULL 不是零地址的机器也是如此。为什么bool是关键字宏_Bool。
这也是按位|和&比 具有更高优先级的原因==,因为有很多(几百千字节安装在三 (3) 台机器上:))源代码,包括诸如if (a==b & c==d). 丹尼斯·里奇承认他应该改变它。https://www.lysator.liu.se/c/dmr-on-or.html
因此,我们至少可以肯定地说,设计选择时考虑到了向后兼容性,后来那些做出选择的人承认这是错误的,并且我们有可靠的来源。
\n还要记住,您的源代码指向 C++ 源代码。在该语言中,有些原因不适用于 C。例如重载。
\n三种 C 字符类型char、signed char和unsigned char作为遗留 C 实现和用法的编码而存在。
将 C 编入第一个 C 标准(现在称为 C89)的 XJ311 委员会在Rational(斜体原文)中阐述了他们的目的:
1.1 目的
该委员会的总体目标是为 C 编程语言制定一个清晰、一致和明确的标准,该标准将通用的、现有的 C 定义编入法典,并促进用户程序在 C 语言环境中的可移植性。
X3J11 章程明确授权委员会将现有的通用做法编纂成法。...
注意:X3J11 委员会特意强调他们正在对 C 的现有实现和常见用法/实践进行编纂,以促进可移植性。
换句话说,“标准”C 从未被创建——现有的 C 代码、用法和实践都被编入了法典。
根据3.1.2.5相同原理的类型(粗体):
指定了三种类型的 char:
signed、 plain 和unsigned。普通 char 可以表示为 或signed,unsigned具体取决于实现,如先前的实践一样。引入signed char类型是为了在那些将普通char实现为无符号的系统上提供单字节有符号整数类型。...
委员会的话说得很清楚:char存在三种类型,因为 plainchar必须是signed或者unsigned才能匹配“先前的实践”。因此, Plainchar必须是独立的 - 可移植代码不能依赖于 plain 的char签名或未签名,但两者signed char都unsigned char必须可用。
由于可移植性问题,这三种字符类型不能以任何方式兼容 - 并且符合标准的 C 代码的可移植性是 XJ311 委员会的主要目标之一。
如果在 plain 未签名的系统上extern char buffer[10]兼容,则如果代码在 plain 已签名的系统上编译*,则代码的行为会有所不同,因此与兼容。例如,位移元素会根据是否通过声明或定义访问而改变行为,从而破坏可移植性。unsigned char buffer[10]charcharunsigned char buffer[10]bufferbufferextern char buffer[10]unsigned char buffer[10];
char在这种情况下,可以以不同的行为签署或取消签署的事实已经存在,并且委员会无法在不违反其目标“codif[y] C 的通用现有定义”的情况下改变这一点。
但以促进可移植性为目标,没有任何理由创造一种疯狂的、引发可移植性噩梦的情况,即“有时char兼容这个不兼容那个,有时char兼容那个不兼容这个”。
* - 如果代码完全编译 - 但这是一个假设,旨在演示为什么这三种char类型必须不兼容。