我发现C99标准有一个声明,它拒绝了char类型和signed char / unsigned char类型之间的兼容性。
C99标准的注释35:
在limits.h中定义的CHAR_MIN将具有值0或SCHAR_MIN之一,这可用于区分这两个选项。无论做出何种选择,char都是与其他两种类型不同的类型,并且与其中任何一种都不兼容。
我的问题是为什么委员会否认兼容性?理由是什么?如果char与signed char或unsigned char兼容,会发生什么可怕的事情吗?
答案 0 :(得分:11)
根位于编译器历史记录中。八十年代基本上有两种C方言:
C89中哪一个应该标准化? C89选择不标准化,因为它会使已编写的C代码中的大量假设无效 - 标准人员称之为已安装的基础。所以C89做了K& R所做的事情:保留了普通字符实现定义的签名。如果您需要特定的签名,请对您的字符进行限定。
现代编译器通常会让你选择带有选项的方言(例如gcc的-funsigned-char
)。
如果忽略(un)signed char和plain char之间的区别,可能发生的“可怕”事情是,如果你在不考虑这些细节的情况下进行算术和移位,那么当你不这样做时,你可能会得到符号扩展期望它们,反之亦然(甚至在转移时也不确定行为)。
还有一些愚蠢的建议,建议总是使用显式签名或无符号限定符声明你的字符。只要您只使用指向这些限定类型的指针,这就可以工作,但只要您处理字符串和字符串函数,它就会需要丑陋的转换,所有这些都在指向普通字符的指针上运行,没有强制转换,它是赋值不兼容的。这样的代码突然变成了大量丑陋的角色。
字符的基本规则是:
char
,如果需要将指针传递给使用plain char unsigned char
如果你需要做一点翻转和转换字节signed char
,但如果空间不是问题,请考虑使用int
答案 1 :(得分:2)
将signed char
和unsigned char
视为最小的算术,整数类型,就像signed short
/ unsigned short
一样,等等int
,{{ 1}},long int
。这些类型都是明确的。
另一方面,long long int
的用途非常不同:它是I / O的基本类型和与系统的通信。它不是用于计算,而是用作数据的单位。这就是为什么你在命令行参数,“字符串”的定义,char
函数和其他读/写类型IO函数中以及在例外中找到char
的原因。严格的别名规则。故意不严格定义此FILE*
类型,以便允许每个实现使用最“自然”的表示。
这只是分离责任的问题。
(诚然,char
布局兼容同时包含char
和signed char
,因此您可以明确地将其中一个转换为另一个然后回来。)