我知道这已经讨论过了,但我想确保我理解正确,这个程序中发生了什么,以及为什么。在Dennis Ritchie的教科书The C Programming Language的第20页,我们看到了这个程序:
#include <stdio.h>
int main()
{
int c;
c = getchar();
while(c != EOF){
putchar(c);
c = getchar();
}
return 0;
}
执行时,程序读取键入的每个字符,并在用户点击进入后以相同的顺序打印出来。除非用户手动退出控制台,否则此过程将无限期重复。事件顺序如下:
getchar()
函数读取键入的第一个字符并将其值分配给c
。c
是一个整数类型,所以getchar()
传递给c的字符值被提升为它对应的ASCII整数值。c
已经初始化为某个整数值,while循环可以测试该值是否等于End-Of-File字符。因为EOF
字符具有-1
的宏值,并且因为没有可能键入的字符具有负的十进制ASCII值,所以while循环的条件将始终为真。c != EOF
为真,则调用putchar()
函数,该函数输出c
中包含的字符值。getchar()
,因此它读取下一个输入字符并将其值传递回while循环的开头。如果用户在执行前只键入一个字符,则程序将<return>
值作为下一个字符读取并打印一个新行并等待下一个输入键入。这是否远程正确?
是的,你基本上得到了它。但它更简单:getchar
和putchar
已分别返回并接受int
类型。所以没有类型推广发生。你只是接受角色并将它们发送出去,直到你看到EOF
。
你对为什么那些应该是int
而不是某些char
形式的直觉可能是正确的:int
类型允许一个超出任何可能的字符值的值范围的sentinel EOF
值。
(此时K&R stdio
功能非常陈旧,他们不了解Unicode等等,并且一些基本的设计原理如果不是模糊的,只是不相关。现在没有很多实用的代码会使用这些功能那本书很适合很多东西,但代码示例相当陈旧。)
(另外,fwiw,你的问题标题是指“复制文件”,你仍然可以这样做,但有更多的规范方法)
嗯,这是正确的想法,但不是详细的,这就是魔鬼的所在。
getchar()
函数从标准输入读取第一个字符并将其作为unsigned char
提升为int
(如果没有读取字符,则返回特殊的EOF
值)c
,其类型为int
(因为它应该为if it were a char
strange things could happen)c
分配了一些整数值,while
循环可以测试该值是否等于EOF
宏的值。EOF
宏具有实现指定的负值,并且因为字符被转换为unsigned char
并被提升为int
,所以它们都没有负值(至少在你遇到的任何系统中都没有),条件while
循环始终为真,直到文件结束条件发生或读取标准输入时发生错误。c != EOF
为真,则调用putchar()
函数,该函数输出c
中包含的字符值。getchar()
,因此它读取下一个输入字符并将其值传递回while循环的开头。我们说的是执行字符集,而不是ASCII,现在可能通常是UTF-8编码的Unicode字符的单个字节。 EOF
也是二进制的负数,我们不需要考虑“它的十进制值”。 char
和unsigned char
类型也是数字,字符常量是int
类型 - 即在执行字符集与ASCII兼容的系统上,写' '
将与写32相同,但当然更清楚不记得ASCII码。
最后,C对初始化的含义非常严格。它是在声明变量时将初始值设置为变量。
int c = getchar();
有一个初始化。
int c;
c = getchar();
有c
未初始化,然后分配一个值。了解这种区别使得在引用初始化或赋值时更容易理解编译器错误消息。