Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么不';t C或C++;标准明确定义字符为有符号还是无符号? < C或C++标准都不指定CHAR为已签名或未签名,它是定义的实现。_C++_C_Types_Compiler Construction_Standards - Fatal编程技术网

为什么不';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;