1

在 Kernighan & Ritchie 中,它说“当 char 数据类型被签名或无符号取决于机器时,所有可打印字符都是正数。”

有人可以向我解释这条线的含义吗?我的系统已经签署了字符,但即使是负值,比如 -90,printf 也会打印一个字符(即使它不是一个非常熟悉的字符)。

4

4 回答 4

2

ASCII 字符集定义从0x00到 的代码点0x7F。它们是用无符号字节值还是有符号字节值表示并不重要,因为这个范围对两者都是通用的。

可打印字符介于0x20和之间0x7E,它们都是 ASCII 的一部分。可打印字符一词并没有定义世界上所有可能的可打印字符。相反,它是在 ASCII 领域内定义的。

0x80从to 到的字节值0xFF在 ASCII 中没有定义,不同的系统将不同的字符分配给此范围内的值,从而导致许多不同类型的代码页在其 ASCII 范围内相同但在此范围内不同。这也是有符号和无符号字节值不同的范围。

的实现在其输入中printf遇到键时查找单个字节值。从您作为函数%c调用者的角度来看,这个字节值可能是有符号或无符号的,但不知道这一点。它只是将这 8 位传递给它所连接的输出流,并且该流在and中发出字符。printfprintf0x000xff

在发出字符的输出管道中,符号的概念没有任何意义。因此,无论您发送 a255还是 a -1,都会发出映射到0xFF特定代码页中的字符。

于 2011-07-18T07:01:57.253 回答
1

-90 作为有符号字符被重新解释为无符号字符,在这种情况下,它的值为 166。(-90 和 166 都是十六进制的 0xA6。)

于 2011-07-18T07:00:52.440 回答
1

这是正确的。所有二进制数都是正数。你是否认为它是负面的,是你自己的解释。使用常见的二的恭维

8 位数:10100110 是正数 166,大于 128(最大正符号 8 位数)。

使用有符号算术,数字 166 是 -90。

您看到的是 ascii 值为 166 的字符。

于 2011-07-18T07:04:45.970 回答
0

以此为例:

signed char x = -90;
printf("%c", x);

整数提升规则在将其作为参数传递给 之前转换x为。(请注意,其他答案都没有提到这个细节,并且有几个暗示参数 to仍然是一个有符号字符)。intprintfprintf

标准的第 7.21.6.1.6 节(我使用的是 C11 标准)谈到了%c标志字符:

如果不存在 l 长度修饰符,则将 int 参数转换为无符号字符,并写入结果字符。

因此整数-90被转换为无符号字符。这意味着(6.​​3.1.3.2):

...通过在新类型中可以表示的最大值重复加或减一,直到该值在新类型的范围内,来转换该值。

如果系统上的 unsigned char 取值 0 到 255(几乎可以肯定),那么结果将是 -90 + 256 = 166。(注意:其他答案是指“最低字节”或“十六进制表示”假设二进制补码表示。虽然这非常普遍,但 C 标准不保证它)。

然后将字符 166 写入标准输出,并由您的终端解释。

于 2020-05-08T09:15:18.853 回答