对 C 中的 int、char 和 EOF 感到困惑

confusion about int, char, and EOF in C

我正在学习 K&R 的经典 C 编程书籍第 2 版,这是第 17 页的示例:

#include <stdio.h>
/* copy input to output*/
main()
{
    int c; 
    // char c works as well!!
    while ((c = getchar()) != EOF)
        putchar(c);
}

书上说int c是用来装EOF的,结果在我的Windows机器上用GCC装的是-1,放不下由 char 表示。但是,当我尝试 char c 时,它没有问题。奇怪的是我又尝试了一些:

int  a = EOF;
char b = EOF;
char e = -1;
printf("%d %d %d %c %c %c \n", a, b, e, a, b, e);

并且输出是 -1 -1 -1,没有显示任何字符(实际上根据 %c, c 的 ASCII table,这里应该显示 nbs(no-break space),但它是不可见的)。

那么如何在没有任何编译器错误的情况下将 char 赋值给 EOF

此外,鉴于EOF-1,上面的be是否都在内存中分配了FF?不应该,否则编译器如何区分 EOFnbs...?

更新

很可能 EOF 0xFFFFFFFF 被转换为 char 0xFF 但在 (c = getchar()) != EOF 中 LHS 0xFF 在比较之前被提升为 0xFFFFFFFF 所以类型 c 可以是 intchar

在这种情况下 EOF 恰好是 0xFFFFFFFF 但理论上 EOF 可以是任何需要超过 8 位才能正确表示的值,最左边的字节不一定是 FFFFFF 那么 char c 方法将失败。

参考: K&R C 编程语言 2e

此代码有效,因为您使用的是 signed chars。如果您查看 ASCII table,您会发现两件事:首先,只有 127 个值。 127用七位来表示,最高位是符号位。其次,EOF不在这个table中,所以OS可以随意定义它。

编译器允许从 charint 的赋值,因为您是从小型类型赋值给大型类型。 int 保证能够表示 char 可以表示的任何值。

另请注意,0xFF 在解释为 unsigned char 时等于 255,在解释为 signed char 时等于 -1:

0b11111111

然而,当表示为 32 位整数时,它看起来非常不同:

255 : 0b00000000000000000000000011111111
-127: 0b11111111111111111111111110000001

EOF0xFF 不一样。所以编译器必须区分它们。如果您看到 man page for getchar(),您就会知道它 returns 字符读取为无符号字符,在文件末尾或错误时转换为 int 或 EOF。

您的 while((c = getchar()) != EOF) 已扩展为

((unsigned int)c != (unsigned int)EOF)