字符是有符号还是无符号的?

3

在哪些情况下我们需要使用有符号的char呢?我猜唯一的用途可能是将char类型的数据转换成整数。


可能是Is char signed or unsigned by default?的重复问题。 - phuclv
6个回答

4
如果我没记错的话,“char”可以是有符号的或无符号的(这取决于编译器/实现)。如果你需要一个无符号字符,你应该明确地要求它(使用“unsigned char”),如果你需要一个有符号字符,你应该明确地要求它(使用“signed char”)。
“char”只是一个(通常为8位的)整数。它与字符无关。
字符可以是任何东西,这取决于你正在做什么。我更喜欢使用“uint32_t”和Unicode(UTF-32)。对于使用ASCII的老旧/损坏软件,char很好(不管“char”是有符号还是无符号)。对于UTF-8,你可能想使用“unsigned char”或“uint8_t”。
你可能也会尝试使用“wchar_t”(和“wchar.h”头文件),但这样做可能会出现很多问题(如果你有兴趣,请进行一些研究)。

4
编译器允许将普通的char设置为有符号是因为在C语言早期,每个整数类型都是有符号的。当无符号类型被添加到语言中时,可能已经存在太多现有代码在char变量中存储-1作为哨兵值,因此不可行将现有系统上的编译器更改为char是无符号的。也许没有任何关于无符号char的巨大压力;C语言的早期开发是在7位ASCII上进行的。
随着C语言移植到支持8位可打印字符的平台(如使用EBCDIC的IBM大型机或PC),那里的编译器将char设置为无符号,因为具有负值的可打印字符会比无法在char中存储-1更大的可移植性问题更加困难。另一方面,这导致了当前的情况,即可移植代码不能对char的符号性做出任何假设。

2

char是一个整数,通常宽度为8位。但由于其符号性取决于实现(即取决于编译器),因此在算术运算中使用它可能不是一个好主意。相反,应该使用unsigned charsigned char,或者如果要强制指定宽度,则可以使用来自stdint.huint8_tint8_t


@tony,你怎么把我的答案编辑成了相反的意思?使用uint8_t会对宽度做出明确的假设,特别是如果存在,则暗示char具有8位宽度。此外,如果那些批准这样的编辑的人(必须有两个人投票支持)更仔细地阅读编辑内容,那就太好了。 - Jens Gustedt
@我不是托尼,但“做出假设”通常意味着你没有确凿的事实依据,而是在猜测。因此,他的更正或多或少意味着“如果你不想猜测宽度,请使用int8_t”等等... 我会完全重新表述这个句子,因为两个版本都有点不清楚。“如果你想要一定的宽度,请使用像int8_t这样的固定大小类型”等等。 - Rudy Velthuis

0

根据你提到的,char是8位整数值。 大多数实际用途来说,它们不需要严格为负数。由于它们必须表示为位,并允许对其执行算术操作,因此将其表示为int。当然,也有unsigned char


1
字符是字节大小,但不一定是8位。确实有具有不同字节宽度的奇特处理器。 - Rudy Velthuis

0
在任何需要表示范围为[-128, 127]的值的地方,signed char都是合适的。如果您有一个包含许多字段的结构体,这些字段将被实例化很多次,那么保持数据类型尽可能小是相关的。

1
我认为你的意思是“有符号字符”。 - Keith Thompson
@Keith Thompson:谢谢,那是一个打字错误。 - Anders Abel

0
在下面的代码中:
signed char c = -1;
printf("%c %d\n", c, c);
c = c >> 1;
printf("%c %d\n", c, c);

如果你使用 unsigned char 而不是 signed char,结果会有所不同(至少在我的“AMD Athlon(tm) 64 Processor”上,在cygwin下使用gcc)。原因是当你对一个无符号值进行右移时,它会用零填充,而当你对一个负的有符号值进行相同操作时,它会用一填充。

虽然我不能确定这是否有用,但这是一个字符符号很重要的情况。


C规范中未定义负数在位移运算符上的行为。请参阅6.5.7位移运算符:“5 E1 >> E2 的结果是将 E1 向右移动 E2 位。如果 E1 具有无符号类型,或者如果 E1 具有带符号类型并且具有非负值,则结果的值是 E1 / 2E2 的商的整数部分。如果 E1 具有带符号类型和负值,则结果是实现定义的。 - xaviersjs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接