K& R C编程语言1.5.1(文件复制)

时间:2012-08-24 13:21:15

标签: c types kernighan-and-ritchie

好吧,我几个月前读过另一本“知名”的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,因为c必须足够大以容纳EOF   除了任何可能的char。因此我们使用int。[...]

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

  

EOF是一个表示文件结尾的特殊宏(Linux:使用CTRL + d on   用于创建此键盘,Windows命令:使用CTRL + z(可能必须   在新行的开头,然后是RETURN)):通常EOF = -1,但是   依赖于实现。必须是不是有效值的值   任何可能的角色。因此,c的类型为int(不是   人们可能已经预料到了。)

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

我也没有不知道getchar如何处理我写的每个角色,并打印所有内容。 Int类型长度为4bytes,因此变量中可以包含4个字符。 但我可以放任意数量的字符,它会以相同的方式读写所有内容。 和char一样,发生了同样的事...... 真的发生了什么?当超过1-4个字符时,值存储在哪里?

3 个答案:

答案 0 :(得分:2)

  

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

发生以同样的方式工作。这一切都取决于char的实际类型,即它是签名还是未签名。关于这个主题还有一个C FAQ。如果您的char未签名,则您更有可能看到该错误。

  

但是,如果是字符,那么该bug很长时间都不会被检测到   签名,如果输入是全部7位字符。

修改

  

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

每个角色将依次由c存储。因此,第一次getchar()将返回s,而putchar将在途中发送它。然后t会出现,依此类推。任何时候c都不会存储多个字符。因此,虽然你给它喂了一个大字符串,但它通过一次吃一个字符来处理它。

答案 1 :(得分:1)

分为两个答案:

为什么int而不是char

简短而正式的答案:如果您希望能够代表所有真实字符和另一个非真实字符(EOF),则不能使用仅设计为真实字符的数据类型字符。

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

因为-1投放到char等于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,则一切都很好,没有人注意到任何内容。

答案 2 :(得分:1)

如果您使用char来存储getchar()的结果,则有两个潜在的问题,您将遇到的问题取决于char的签名。

  • 如果char未签名,c == EOF将永远不会成立,您将获得无限循环。

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