默认情况下,char是签名还是未签名?


158

在“ C的完整引用”一书中,提到char默认情况下是无符号的。

但是我试图用GCC和Visual Studio对此进行验证。默认情况下将其视为已签名

哪一个是正确的?


5
我信任的一本C参考书是Harbison&Steele的“ C:参考手册”(careferencemanual.com)。当然,标准是最终的词汇,但是它不是很可读,只能提供有关标准以外的标准前和常见用途(即POSIX)的信息。Harbison&Steele与大多数参考文献相比,可读性强,详细且可能更正确。但是,它也不是教程,因此,如果您处于学习的初始阶段,则可能不是一件好事。
Michael Burr 2010年

15
我认为您正在阅读的书是Herbert Schildt 撰写的C:The Complete Reference。从这本书的评论(accu.informika.ru/accu/bookreviews/public/reviews/c/c002173.htm): 我不会推荐这本书(你们中有太多人对我的观点太有分量了),但是我认为这不应该像他在其他一些作品中所提出的那样pro亵。 正如迈克尔所说,更好的参考是Harbison&Steele
Alok Singhal'1

我在这里的两个美分:因为char可以是无符号的,所以根据经验,可以使用an int来读取using的值getchar(),该值可能会返回EOFEOF通常定义为-1或其他负值,而unsigned不是要存储在中。这是声明:extern int getchar();顺便说一句,此建议也来自“ C:参考手册”一书。
Maxim Chetrusca 2014年

6
我信任的一个C参考是ISO / IEC 9899:2011 :-)
Jeff

3
@MaxChetrusca是个好的建议,但有一个不好的理由:即使在签名的char案例中,您也必须使用它int来存储返回值。
Antti Haapala'2

Answers:


204

这本书是错的。该标准未指定Plain char是带符号的还是无符号的。

实际上,标准定义了三种不同的类型:charsigned char,和unsigned char。如果#include <limits.h>再查看CHAR_MIN,则可以找出plain char是否为signedunsigned(如果CHAR_MIN小于0或等于0),但是即使这样,就标准而言,这三种类型也是不同的

请注意,char这种方式很特别。如果将变量声明为int,则等同于将其声明为signed int。所有编译器和体系结构始终如此。


1
@Alok:对于其他一些数据类型,情况并非如此,例如,总是int意味着signed int对吧?除此之外char,还有哪些其他数据类型具有相同的困惑C
Lazer

8
@eSKay:是的,char是唯一可以签名或未签名的类型。 int等价signed int于例如。
Alok Singhal 2010年

28
有一个歇斯底里的历史原因–在C语言的生命早期,“标准”至少被两次翻转,并且一些流行的早期编译器以一种方式结束,而另一种以另一种方式结束。
2012年

9
@AlokSinghal:这也是实现定义的,是类型的位字段int是带符号的还是无符号的。
基思·汤普森

@KeithThompson感谢您的纠正。我倾向于忘记一些有关位字段类型的细节,因为我很少使用它们。
阿洛克辛格

67

正如Alok指出的那样,该标准由实施来决定。

对于gcc,默认设置是带符号的,但是您可以使用进行修改-funsigned-char注意:对于Android NDK中的gcc,默认值为unsigned。您也可以使用明确要求输入签名字符-fsigned-char

在MSVC上,默认设置是带符号的,但您可以使用进行修改/J


2
有趣的是,希尔德的描述与MSVC的行为不符,因为他的书通常是针对MSVC用户的。我想知道MS是否在某个时候更改了默认设置?
Michael Burr 2010年

1
我认为它不依赖于编译器,而是依赖于平台。我以为char保留为“字符数据类型”的第三种类型,以符合当时用作可打印字符的系统的要求。
蜘蛛侠2012年

10
GCC文档说这是与机器有关的:“ 每种机器都有默认的char字符。默认情况下,它就像是unsigned char一样,默认情况下就像是signed char。
Deduplicator

1
您能否提供注释来源,说明在android上默认为unsigned char?
phlipsy 2015年

1
@Spidey C标准在编译器,平台和CPU体系结构之间没有真正的区别。它只是将它们全部混入“实现”中。
plugwash

35

C99 N1256草案 6.2.5 / 15“类型”对类型的签名有此说法char

实现应将char定义为具有与签名char或未签名char相同的范围,表示形式和行为。

并在脚注中:

CHAR_MIN在中定义的<limits.h>,将具有0或值之一SCHAR_MIN,并且可用于区分这两个选项。不管做出char何种选择,它都是与其他两种类型分开的类型,并且与任何一种都不兼容。


7

根据Dennis Ritchie的《 C编程语言》一书,这是ANSI C的事实上的标准书,有符号或无符号的纯字符都取决于机器,但可打印字符始终为正。


9
可打印字符不一定总是正数。C标准保证基本执行字符集的所有成员都具有非负值。
基思·汤普森

7

根据C标准,纯字符的签名是“实现定义的”。

通常,实现者选择在其体系结构上实现效率更高的那个。在x86系统上,通常对char进行签名。在手臂系统上,它通常是未签名的(Apple iOS是一个例外)。



2
@plugwash您的答案可能被否决了,因为Tim Post丢了他的钥匙。认真地说,只要您确定答案正确(在这种情况下就是如此),就不必担心一次投票失败。我无数次无缘无故地减免了我的帖子。不用担心,有时候人们只是在做奇怪的事情。
唐老鸭

1
为什么在x86上签名的char更有效?有资料吗?
martinkunev

2

根据Bjarne Stroustrup的“ C ++编程语言”,char定义为“实现”。它可以是signed charunsigned char取决于实现。您可以使用来检查是否char已签名std::numeric_limits<char>::is_signed


9
这是一个C问题。C ++是一种不同的语言和C ++基准具有没有相关性C.
MM

1

现在,我们知道该标准由实施决定。

但如何检查类型是signedunsigned,如char

我写了一个宏来做到这一点:

#define IS_UNSIGNED(t) ((t)~1 > 0)

与测试gccclang以及cl。但是我不确定在其他情况下它是否总是安全的。


通常的CHAR_MIN <0(对于wchar_t,或WCHAR_MIN <0)有什么问题?
二OO Tiib
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.