关于将getchar()返回值存储在char变量中

时间:2013-09-26 12:31:52

标签: c getchar

知道以下代码已损坏 - 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不能存储在单个字节中......

提前谢谢

5 个答案:

答案 0 :(得分:1)

  

知道以下代码已损坏 - getchar()返回int而不是char -

好!

char single_byte = getchar();

这有问题不止一种方式。

我会假设CHAR_BIT == 8EOF == -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)。

所以这段代码不起作用!要么你必须定义一个值来退出代码!