好吧,我几个月前读过另一本“知名”的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个字符时,值存储在哪里?
答案 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
,但您很少能保证您的问题将保留在签名字符串实现上,并且仅用于非有问题的语言环境。