对 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
,上面的b
和e
是否都在内存中分配了FF
?不应该,否则编译器如何区分 EOF
和 nbs
...?
更新:
很可能 EOF 0xFFFFFFFF
被转换为 char 0xFF
但在 (c = getchar()) != EOF
中 LHS 0xFF
在比较之前被提升为 0xFFFFFFFF
所以类型 c
可以是 int
或 char
。
在这种情况下 EOF
恰好是 0xFFFFFFFF
但理论上 EOF
可以是任何需要超过 8 位才能正确表示的值,最左边的字节不一定是 FFFFFF
那么 char c
方法将失败。
参考:
K&R C 编程语言 2e
此代码有效,因为您使用的是 signed char
s。如果您查看 ASCII table,您会发现两件事:首先,只有 127 个值。 127用七位来表示,最高位是符号位。其次,EOF
不在这个table中,所以OS可以随意定义它。
编译器允许从 char
到 int
的赋值,因为您是从小型类型赋值给大型类型。 int
保证能够表示 char
可以表示的任何值。
另请注意,0xFF
在解释为 unsigned char
时等于 255,在解释为 signed char
时等于 -1:
0b11111111
然而,当表示为 32 位整数时,它看起来非常不同:
255 : 0b00000000000000000000000011111111
-127: 0b11111111111111111111111110000001
EOF
和 0xFF
不一样。所以编译器必须区分它们。如果您看到 man page for getchar()
,您就会知道它 returns 字符读取为无符号字符,在文件末尾或错误时转换为 int 或 EOF。
您的 while((c = getchar()) != EOF)
已扩展为
((unsigned int)c != (unsigned int)EOF)
我正在学习 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
,上面的b
和e
是否都在内存中分配了FF
?不应该,否则编译器如何区分 EOF
和 nbs
...?
更新:
很可能 EOF 0xFFFFFFFF
被转换为 char 0xFF
但在 (c = getchar()) != EOF
中 LHS 0xFF
在比较之前被提升为 0xFFFFFFFF
所以类型 c
可以是 int
或 char
。
在这种情况下 EOF
恰好是 0xFFFFFFFF
但理论上 EOF
可以是任何需要超过 8 位才能正确表示的值,最左边的字节不一定是 FFFFFF
那么 char c
方法将失败。
参考: K&R C 编程语言 2e
此代码有效,因为您使用的是 signed char
s。如果您查看 ASCII table,您会发现两件事:首先,只有 127 个值。 127用七位来表示,最高位是符号位。其次,EOF
不在这个table中,所以OS可以随意定义它。
编译器允许从 char
到 int
的赋值,因为您是从小型类型赋值给大型类型。 int
保证能够表示 char
可以表示的任何值。
另请注意,0xFF
在解释为 unsigned char
时等于 255,在解释为 signed char
时等于 -1:
0b11111111
然而,当表示为 32 位整数时,它看起来非常不同:
255 : 0b00000000000000000000000011111111
-127: 0b11111111111111111111111110000001
EOF
和 0xFF
不一样。所以编译器必须区分它们。如果您看到 man page for getchar()
,您就会知道它 returns 字符读取为无符号字符,在文件末尾或错误时转换为 int 或 EOF。
您的 while((c = getchar()) != EOF)
已扩展为
((unsigned int)c != (unsigned int)EOF)