为什么不';t C或C++;标准明确定义字符为有符号还是无符号? < C或C++标准都不指定CHAR为已签名或未签名,它是定义的实现。
为什么不';t C或C++;标准明确定义字符为有符号还是无符号? < C或C++标准都不指定CHAR为已签名或未签名,它是定义的实现。,c++,c,types,compiler-construction,standards,C++,C,Types,Compiler Construction,Standards,为什么C/C++标准没有明确地将char定义为有符号或无符号,以避免像上述代码那样的危险误用?主要是历史原因 在大多数上下文中,char类型的表达式被提升为int(因为许多CPU没有8位算术运算)。在某些系统上,符号扩展是实现这一点的最有效的方法,它支持使用纯char符号 另一方面,EBCDIC字符集具有具有高阶位集的基本字符(即,具有128或更大值的字符);在EBCDIC平台上,char几乎必须是未签名的 (对于1989年的标准)在这个问题上没有太多的话要说;第3.1.2.5节规定: 指定了三
为什么C/C++标准没有明确地将char定义为有符号或无符号,以避免像上述代码那样的危险误用?主要是历史原因 在大多数上下文中,
char
类型的表达式被提升为int
(因为许多CPU没有8位算术运算)。在某些系统上,符号扩展是实现这一点的最有效的方法,它支持使用纯char
符号
另一方面,EBCDIC字符集具有具有高阶位集的基本字符(即,具有128或更大值的字符);在EBCDIC平台上,char
几乎必须是未签名的
(对于1989年的标准)在这个问题上没有太多的话要说;第3.1.2.5节规定:
指定了三种类型的字符:有符号的
、普通字符和无符号的
。A.
普通字符可以表示为有符号或无符号,具体取决于
在实施时,如在先前的实践中。类型有符号字符
是为了在上提供一个单字节有符号整数类型
那些将纯字符实现为无符号的系统。由于
对称,关键字signed
可以作为
其他积分类型
更进一步说,1975年的早期版本说:
char
对象可以在int
的任何位置使用。在所有情况下
char
通过将其符号传播到上半部分来转换为int
结果整数的8位。这与两人的观点是一致的
用于字符和整数的补码表示法。
(但是,符号传播功能在其他情况下消失。)
实现。)
这个描述比我们在后面的文档中看到的更具体于实现,但是它承认char
可以是有符号的,也可以是无符号的。在“符号传播消失”的“其他实现”中,将char
对象提升为int
将零扩展8位表示,本质上将其视为8位无符号量。(该语言还没有有符号
或无符号
关键字。)
C的直接前身是一种称为B的语言。B是一种无类型语言,因此char
被签名或未签名的问题不适用。有关C语言早期历史的更多信息,请参见已故的丹尼斯·里奇,现在
至于代码中发生了什么(应用现代C规则):
如果纯char
是无符号的,则c
的初始化将其设置为(char)0xff
,这将与第二行中的0xff
进行比较。但是如果对纯char
进行了签名,那么0xff
(类型为int
的表达式)将转换为char
——但是由于0xff
超过char\u MAX(假设char\u位==8
),因此结果是实现定义的。在大多数实现中,结果是-1
。在比较中,0xff==c
,两个操作数都转换为int
,使其等效于0xff==-1
,或255==-1
,这当然是错误的
另一个需要注意的重要事项是,无符号字符
、有符号字符
和(普通)字符
是三种不同的类型char
与unsigned char
或signed char
具有相同的表示形式;它的实现定义了它是哪一个。(另一方面,signed int
和int
是同一类型的两个名称;unsigned int
是一个不同的类型。(除了,为了增加轻浮性,它的实现定义了声明为纯int
的位字段是有符号的还是无符号的。)
是的,这一切都有点混乱,我相信如果C是从零开始设计的话,它的定义会有所不同。但是C语言的每一次修订都必须避免破坏(太多)现有代码,并在较小程度上破坏现有的实现。
char
最初是用来存储字符的,所以它是有符号的还是无符号的并不重要。真正重要的是如何有效地对char
执行数学运算。因此,取决于系统,编译器将选择最合适的
在ARMv4之前,ARM不支持加载半字和有符号字节。要加载有符号字节,必须先对LDRB进行签名,然后对值进行扩展(先向上LSL,然后向下ASR)。这很痛苦,因此默认情况下,char是未签名的
事实上,许多ARM编译器在默认情况下仍然使用无符号字符
,因为即使可以在现代ARM ISAs上加载带符号扩展名的字节,该指令仍然不如零扩展名版本灵活
大多数现代编译器还允许您更改字符的符号,而不是使用默认设置没有“C/C++标准”标准。但问题是这两个标准都有。通常,标准都没有明确定义,以便实现灵活地执行他们认为适合(或快速)其平台的任何操作。@teppic:不正确
int
始终等于signed int
unsigned int
是一种不同的类型。//b始终为FALSE
@WhozCraig:是的,但这并不能解释为什么它是实现定义的。侧栏:AS/400和OS/390都极大地利用了它们各自的EBCDIC字符集的位布局,用于在底层硬件中实现的基树。很难得到比THO更多的实现定义
int main()
{
char c = 0xff;
bool b = 0xff == c;
// Under most C/C++ compilers' default options, b is FALSE!!!
}
char c = 0xff;
bool b = 0xff == c;