在 C 中处理字符和整数时的神秘 ASCII 值

Mysterious ASCII value when working with chars and integers in C

在 C 中,char 查找 ASCII 中的值(但不会变成整数)的想法是有道理的。

我写了一些代码来说明这一点,其中一个大于 256 的整数值(256 个可能的值和 ASCII 项的总数)环绕到 ASCII 的开头,或者 0。我感兴趣的是这个算术可以在以整数 d 开始并在字符 c 上加上一个整数时执行。

// C starts as a character
char c = 'c';
printf("c equals %i\n", c);
printf("c in ascii: %c\n", c);
printf("\n");

// I starts as an integer
int i = 105;
printf("i equals %i\n", i);
printf("i in ascii: %c\n", i);
printf("\n");

// Using arithmetic on character 'c'
int d = c + 1;
printf("d equals %i\n", d);
printf("d in ascii: %c\n", d);
printf("\n");

// The value of a in ascii (97) + the number of ascii characters (256)
int a = 353;
printf("a equals %i\n", a);
printf("a in ascii: %c\n", a);

Output:
c equals 99
c in ascii: c

i equals 105
i in ascii: i

d equals 100
d in ascii: d

a equals 353
a in ascii: a

然而,我遇到了一个谜,从一个char d开始,然后将一个整数加到另一个char c上。

// This makes sense...
char c = 'c';
int z = c + 100;
// But I would expect d to equal 199 as for z
char d = c + 100;

printf("c equals %i\n", c);
printf("z equals: %i\n", z);
printf("d equals %i\n", d);
printf("d equals %c\n", d);

Output:
c equals 99
z equals: 199
d equals -57
d equals 
当作为字符调用时,

d 神秘地变为 -57 和 returns 空白 space。调试器显示 d 的 ASCII 值是“\307”,我无法解释。

The idea that in C a char looks up a value in ASCII (but doesn't become an integer) makes sense.

在 C 中,字符常量是一个整数,类型为 int

C 实现不一定使用 ASCII。编译器通常不必查找它,因为它接收的源代码已经编码为文件或流中的字节。它可能必须在不同的字符编码之间进行一些转换,例如在 ASCII 和 UTF-8 之间。

I wrote some code to illustrate this point, in which an integer value above 256 (256 possible values and the total number of ASCII items) wraps around to the beginning of ASCII, or 0.

你不应该在不理解的情况下依赖这种行为。它可能并不总是那样发生。

int a = 353;
printf("a equals %i\n", a);
printf("a in ascii: %c\n", a);

当使用 %c 转换时,根据 C 2018 7.21.6.1 8,为其传递的值将转换为 unsigned char。在常见的 C 实现中,unsigned char 是八位。根据 C 2018 6.3.1.3 2,此转换以 256 为模;它像你描述的那样包装。打印代码为 353−256 = 97 的字符。这与 ASCII 无关;这是 unsigned char 使用八位的结果。如果 C 实现使用 ASCII,则 97 的值将导致打印“a”。

char c = 'c';
int z = c + 100;
char d = c + 100;

printf("d equals %i\n", d);
printf("d equals %c\n", d);

char d = c + 100;中,使用int类型进行运算。这是因为 100 是一个 int 常量,而 + 的操作数被转换为具有公共类型。 (对此有一些复杂的规则。)鉴于字符 'c' 的值为 99,因此变量 c 为 99,c + 100 产生 199。

然后 char d 初始化为 199。C 标准允许 char 有符号或无符号。在您的实现中,char 是有符号的八位,值范围从 −128 到 +127。所以199不能用char表示。然后C 2018 6.3.1.3 3中的规则说199转换为实现定义的值或产生信号。

您的实现似乎包含了这个值模 256。所以结果是 199−256 = −57,可以用 char 表示,所以 d 被初始化为 57。

然后,当你用%i打印这个时,打印出“-57”。

当您使用“%c”打印时,它会转换为 unsigned char,如上所述。这会产生 −57+256 = 199。这不是 ASCII 字符的代码,因此您的 C 实现打印它具有值 199 的任何字符。这可能显示为空白 space.

A debugger shows me that d has an ASCII value of '7',…

\nnn是常用的八进制字符书写方式。 7表示3078 = 3•82 + 0•81 + 7 •80 = 3•64 + 0•8 + 7•1 = 192 + 0 + 7 = 199.