我知道以下代码已损坏 - getchar()
返回int
而不是char
-
#include <stdio.h>
int
main(int argc, char* argv[])
{
char single_byte = getchar();
while (single_byte != EOF) {
single_byte = getchar();
printf("getchar() != EOF is %d.\n", single_byte != EOF);
if (single_byte == EOF)
printf("EOF is implemented in terms of 0x%x.\n", single_byte);
}
return 0;
}
虽然我希望它的典型输出(例如使用/dev/urandom
作为输入流)最后EOF is implemented in terms of 0xff
,不以下
$ ./silly < /dev/urandom
getchar() != EOF is 1.
getchar() != EOF is 1.
// ...
getchar() != EOF is 0
EOF is implemented in terms of 0xffffffff.
此外,0xffffffff
不能存储在单个字节中......
提前谢谢
答案 0 :(得分:1)
我知道以下代码已损坏 -
getchar()
返回int
而不是char
-
好!
char single_byte = getchar();
这有问题不止一种方式。
我会假设CHAR_BIT == 8
和EOF == -1
。 (我们知道EOF
为负数且类型为int
; -1
是典型值 - 实际上我从未听说过它有任何其他价值。)
普通char
可以是已签名或未签名。
如果它是无符号的,single_byte
的值将是刚刚读取的字符的值(表示为unsigned char
并且平均转换为普通char
),或者将EOF
转换为char
的结果。通常EOF
为-1,转换结果为CHAR_MAX
或255.您将无法区分EOF
和实际输入值255 - 并且由于/dev/urandom
以相同的概率返回所有字节值(并且永远不会干掉),所以迟早会看到0xff
个字节。
但是这不会终止你的输入循环。你的比较(single_byte == EOF)
永远不会成真;由于single_byte
在此方案中属于无符号类型,因此它永远不能等于EOF
。即使从有限文件而不是像/dev/urandom
这样的无限制设备中读取,您也会有一个无限循环。 (你可以写(single_byte == (char)EOF)
,但当然这不会解决潜在的问题。)
由于你的循环确实终止了,我们可以得出结论,你的系统上已经签署了普通的char
。
如果签署了普通char
,事情就会复杂一些。如果您读取0..127范围内的字符,其值将存储在single_byte
中。如果您读取128..255范围内的字符,则int
值已转换至char
;由于char
已签名且值超出范围,因此转换结果为实现定义。对于大多数实现,该转换将128映射到-128,129到-127,... 255到-1。如果getchar()
返回EOF
(通常为-1),则转换定义良好并产生-1。同样,您无法区分EOF
和值为-1
的输入字符。
(实际上,从C99开始,转换也可以引发实现定义的信号。幸运的是,据我所知,实际上并没有实现。)
if (single_byte == EOF)
printf("EOF is implemented in terms of 0x%x.\n", single_byte);
同样,如果getchar()
实际返回EOF
或者您刚刚读取了值为0xff
的字符,则此条件为真。 %x
格式需要unsigned int
类型的参数。 single_byte
类型为char
,几乎可以肯定会提升为int
。现在,您可以使用int
格式打印unsigned int
值,如果值在两种类型的可表示范围内。但由于single_byte
的值为-1
(它只是等于EOF
),因此它不在该范围内。 printf
,"%x"
格式,假设参数类型为unsigned int
(这不是转化)。 0xffffffff
可能会导致int
的{{1}}值为32 -1
,并假设它真的是unsigned int
。
我要注意的是,将getchar()
的结果存储在int
对象中要比分析char
中存储的内容要容易得多。
答案 1 :(得分:0)
End-of-File是int类型的宏定义,它扩展为负整数常量表达式(通常为-1)。
答案 2 :(得分:0)
EOF
不是真正的字符,所以为了让getchar()
的结果返回有效字符或EOF
,它使用hack而返回类型为{{ 1}}。您必须在之后将其投放到int
,以确保它不是char
。
这是API设计不佳的教科书示例。
答案 3 :(得分:0)
这似乎是(char) -1
和(int) -1
之间的混淆。
getchar()
返回int
,其中包含257个不同值中的1个:0到255和EOF。 EOF小于0(C11 7.21.1)。
通常 EOF的值为-1,在您的情况下也是如此。让我们假设以下内容。
有时,从/dev/urandom
读取数据时,会读取值255。这是不是 EOF。
如果OP执行char single_byte = getchar()
,single_byte
如果(char) -1
(EOF)被读取或{是(int) -1
,则会(int) 255
的相同值{1}}已被阅读。
下次比较single_byte != EOF
时,如果结果为false
,我们不知道getchar()
的原始返回值是-1还是255.
推荐其他printf()
printf("single_byte==EOF, so (int) 255 or EOF was read: 0x%hhx\n", single_byte);
假设:
char
是8位
EOF是-1。
答案 4 :(得分:0)
EOF values are
EOF => %d => -1
EOF => %c => <prints blank space but not blank space>
EOF => %x => 0xFFFFFFFF
EOF没有ascii值!所以基本上你不能将getchar()输出与EOF进行比较。原因是当你留空格并按下输入时,空格的ASCII值为0x20(十进制为32),如果按回车键,则回车的ASCII为0x0D(十进制为13)。
所以这段代码不起作用!要么你必须定义一个值来退出代码!