0

好吧,几个月前我读过另一本“众所周知”的C书(用我的语言),我从来没有学到任何东西。K&R 在 20 页中写了 3 章的方式简直令人惊叹,当然我不能指望巨大的解释,但这也引发了问题。

我对这一点有疑问 1.5.1 这本书说(第 16 页):

main(){
  int c;// <-- Here is the question
  c=getchar();
  while (c != EOF){
    putchar(c);
    c = getchar();
  }
}

[...] char 类型专门用于存储此类字符数据,但可以使用任何整数类型。我们使用 int 是出于一个微妙但重要的原因。问题在于将输入的结尾与有效数据区分开来。解决方案是 getchar 在没有更多输入时返回一个独特的值,该值不能与任何真实字符相结合。此值称为 EOF,表示“文件结束”。我们必须声明 c 是一个足够大的类型来保存 getchar 返回的任何值。我们不能使用 char,因为除了任何可能的 char 之外,c 必须足够大以容纳 EOF。因此我们使用 int.[...]

在谷歌搜索另一种解释后:

EOF 是一个表示文件结束的特殊宏(Linux:使用键盘上的 CTRL+d 来创建它,Windows 命令:使用 CTRL+z(可能必须在新行的开头,后跟 RETURN)):通常 EOF = -1,但依赖于实现。必须是对于任何可能的字符都不是有效值的值。出于这个原因, c 是 int 类型(不是人们可能期望的 char )。

所以我将源代码从 int 修改为 char 以查看有什么问题,关于取 EOF 值......但没有问题。以同样的方式工作。

我也没有破坏 getchar 如何获取我写的每个字符并打印所有内容。Int 类型是 4 字节长,因此它可以在一个变量中占用 4 个字符。但我可以输入任意数量的字符,它会以相同的方式读取和写入所有内容。而对于 char,也会发生同样的情况……真正发生了什么?超过 1-4 个字符时,值存储在哪里?

4

3 回答 3

2

所以我将源代码从 int 修改为 char 以查看有什么问题,关于取 EOF 值......但没有问题。以同样的方式工作

碰巧也以同样的方式工作。这完全取决于 的真实类型char,即它是有符号的还是无符号的。还有一个关于这个主题的C 常见问题解答。如果您char的 s 未签名,您更有可能看到该错误。

但是,如果字符已签名并且输入全是 7 位字符,则该错误可能会在很长一段时间内未被检测到。

编辑

最后一个问题是:char类型是一个字节长,int是4个字节长。所以,char 只会占用一个 ascii 字符。但是如果我输入“堆栈溢出超过 1 个字节长”,输出将是“堆栈溢出超过 1 个字节长”。“tack overflow is over 1byte long”存储在哪里,putchar如何放置整个字符串

每个字符将被c依次存储。所以第一次,getchar()将返回s,并将putchar在途中发送。然后t会来等等。在任何时候都不会c存储一个以上的字符。因此,尽管您给它输入一个大字符串,但它通过一次吃一个字符来处理它。

于 2012-08-24T13:26:06.713 回答
1

分成两个答案:

为什么int和不char

简短而正式的回答:如果您希望能够表示所有真实字符和另一个非真实字符 (EOF),则不能使用旨在仅保存真实字符的数据类型。

可以理解但不完全准确的答案:该函数getchar()返回它读取的字符的 ASCII 码,或 EOF。

因为-1cast tochar等于 255,所以我们无法区分 255 字符和 EOF。那是,

char a = 255;
char b = EOF;
a == b // Evaluates to TRUE

但,

int a = 255;
int b = EOF;
a == b // Evaluates to FALSE

因此,使用char将不允许您区分 ASCII 码为 255 的字符(从文件读取时可能发生)和 EOF。

你怎么能用putchar()一个int

该函数putchar()查看它的参数,看到一个数字,然后转到 ASCII 表并绘制它看到的字形。当您将其传递给 时int,它会被隐式转换为char. 如果 中的数字int适合char,一切都很好,没有人注意到任何事情。

于 2012-08-24T13:34:26.567 回答
1

如果您char用于存储 的结果getchar(),则存在两个潜在问题,您将遇到哪一个取决于char.

  • 如果char是无符号的,c == EOF永远不会是真的,你会得到一个无限循环。

  • 如果char已签名,c == EOF则当您输入一些字符时将为真。这取决于使用的字符集;在使用 ISO8859-1 或 CP852 的语言环境中,如果 EOF 为 -1(最常见的值),则为“ÿ”。某些字符集,例如 UTF-8,不使用(char)EOF有效代码中的值,但您很少能保证您的问题将停留在有符号字符实现上,并且仅在无问题的语言环境中使用。

于 2012-08-24T13:38:10.647 回答