2

知道下面的代码被破坏了——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不能存储到单个字节中......

先感谢您

4

5 回答 5

1

知道下面的代码被破坏了——getchar()返回一个int不是char——

好的!

char single_byte = getchar();

这是有问题的不止一种方式。

我会假设CHAR_BIT == 8EOF == -1。(我们知道EOF负数和类型int;-1是一个典型的值——事实上我从来没有听说过它有任何其他值。)

Plainchar可以是签名的或未签名的。

如果它是无符号的,则 的值single_byte将是刚刚读取的字符的值(表示为 anunsigned char并简单地转换为 plain char),或者转换EOFchar. 通常EOF为 -1,转换结果将为CHAR_MAX, 或 255。您将无法区分EOF255 和实际输入值 - 因为/dev/urandom以相等的概率返回所有字节值(并且永远不会干涸) ,你0xff迟早会看到一个字节。

但这不会终止您的输入循环。你的比较(single_byte == EOF)永远不会是真的;因为single_byte在这种情况下是无符号类型,所以它永远不能等于EOF. 即使从有限文件而不是从无限设备(如/dev/urandom. (您可以编写(single_byte == (char)EOF),但当然这不能解决根本问题。)

由于您的循环确实终止了,我们可以得出结论,plainchar在您的系统上已签名。

如果plainchar被签名,事情会稍微复杂一些。如果您读取 0..127 范围内的字符,则其值将存储在single_byte. 如果您读取 128..255 范围内的字符,则该int值将转换char; 因为char是有符号的并且值超出范围,所以转换的结果是实现定义的。对于大多数实现,该转换会将 128 映射到 -128、129 到 -127、... 255 到 -1。如果getchar()返回EOF(通常)为-1,则转换定义明确并产生-1。同样,您无法区分EOF和 输入字符与 value -1

(实际上,从 C99 开始,转换也可以引发实现定义的信号。幸运的是,据我所知,实际上没有实现这样做。)

if (single_byte == EOF)
    printf("EOF is implemented in terms of 0x%x.\n", single_byte);

getchar()同样,如果实际返回EOF或者您只是读取具有 value 的字符,则此条件将为真0xff。该%x格式需要一个类型为 的参数unsigned intsingle_byte是类型char,几乎肯定会被提升为int. 现在,如果值在两种类型的可表示范围内,您可以int使用unsigned int格式打印值。但由于' 的值是(它只是比较等于),它不在那个范围内。, 使用格式,假设参数是类型的(这不是转换)。并且是采用 32 位值的可能结果single_byte-1EOFprintf"%x"unsigned int0xffffffffint-1并假设它真的是一个unsigned int.

我只想指出,将 的结果存储getchar()在一个int对象中要比分析将其存储在char.

于 2013-09-26T15:00:32.480 回答
0

End-of-File 是 int 类型的宏定义,它扩展为负整数常量表达式(通常为 -1)。

于 2013-09-26T12:34:06.323 回答
0

EOF不是真正的字符,因此为了允许getchar()返回有效字符或 的结果EOF,它使用 hack 而返回类型为int. 在确保它不是char .EOF

这是一个设计不佳的 API 的教科书示例。

于 2013-09-26T13:49:35.250 回答
0

这似乎是 和 之间的(char) -1混淆(int) -1

getchar()返回int257 个不同值中的 1 个:0 到 255 和 EOF。EOF 小于 0 (C11 7.21.1)。

通常EOF 的值为 -1,在您的情况下也是如此。让我们假设以下内容。

有时,从 读取数据时,会读取/dev/urandom255 的值。这不是EOF。

鉴于 OP 执行char single_byte = getchar(),single_byte采用相同的值(char) -1if (int) -1(EOF) was read 或 if (int) 255was read.

下次比较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。

于 2013-09-26T13:53:36.770 回答
0
EOF values are
EOF => %d => -1
EOF => %c => <prints blank space but not blank space>
EOF => %x => 0xFFFFFFFF

EOF 没有 ascii 值!所以基本上你不能将 getchar() 输出与 EOF 进行比较。原因是当您离开空格并按 Enter 时,空格的 ASCII 值为 0x20(十进制的 32),如果按 Enter,则回车的 ASCII 为 0x0D(十进制的 13)。

所以那段代码是行不通的!要么您必须定义一个值才能退出代码!

于 2013-09-26T14:11:08.670 回答