1、关于EOF(end of file)
- EOF不是一个特殊字符
- EOF并不存在于文件末尾
- EOF只是c/c++标准库中的一个宏定义,它的值是-1
EOF并不是一个特殊字符,它也不存在于文件末尾以指示文件结束,它只是一个宏,一个函数执行读取操作时发生错误或遇到文件结尾时返回的值(-1)。
还有一点,windows和linux操作系统并不需要一个EOF标志字符来指示文件的末尾,通过文件系统,它们自始自终都知道一个文件的确切大小(以字节为单位)
2、文件结束标识符的由来
虽然在windows和linux操作系统中并不存在end-of-file标记字符,但是你,在很久之前,它是存在过的。有一个叫做cm/p的操作系统,它的文件系统并不知道一个文件的确切字节大小(它所只知道的只是一个文件占用了多少磁盘块)。随着越来越多的人更想知道文件的确切字节大小而不是所占用的磁盘块,end-of-file标记字节应运而生,cm/p利用Ascll字符Ctrl-Z(十进制值为26)作为标记字节来指示文件的结尾。通过这种方法,cm/p操作系统可以知道一个文件的确切字节大小。
而随后出现的MS-DOS与cm/p保持了兼容,沿用了以Ctrl-Z作为标记字节的做法。
3、Ctrl-D,Ctrl-Z,Ctrl-C
这里引用阮一峰先生在他网络日志中的一段话来回答:
原文链接(http://www.ruanyifeng.com/blog/2011/11/eof.html)
标准输入与文件不一样,无法事先知道输入的长度,必须手动输入一个字符,表示到达EOF。
Linux中,在新的一行的开头,按下Ctrl-D,就代表EOF(如果在一行的中间按下Ctrl-D,则表示输出"标准输入"的缓存区,所以这时必须按两次Ctrl-D);Windows中,Ctrl-Z表示EOF。(顺便提一句,Linux中按下Ctrl-Z,表示将该进程中断,在后台挂起,用fg命令可以重新切回到前台;按下Ctrl-C表示终止该进程。)
那么,如果真的想输入Ctrl-D怎么办?这时必须先按下Ctrl-V,然后就可以输入Ctrl-D,系统就不会认为这是EOF信号。Ctrl-V表示按"字面含义"解读下一个输入,要是想按"字面含义"输入Ctrl-V,连续输入两次就行了。
4、为什么要用int类型接收getchar的返回值
int main(void) {
//unsigned char c;
int c;
while ((c=getchar())!=EOF){
putchar(c);
}
}
之所以c使用int类型而不是char类型的理由如下:
首先要说明的是有些编译器将char当作有符号数来处理,而有些编译器则把char看成无符号类型的,并且像getchar()之类的函数的返回值的类型是int。
一、假如char是无符号类型:
- 当读取结束,getchar()返回EOF(-1)
- 此时执行c=getchar(),发生类型转换(int—>unsignd char),0xFFFFFFFF(有符号表示:-1)截断为0xFF(无符号表示:255)
- 执行判断c!=EOF,因为EOF是int类型,发生类型转换(unsigned char—>int)
,0xFF无符号数零扩展为0x000000FF(有符号数255),0x000000FF!=0xFFFFFFFF,继续循环
因此若char是无符号类型则会导致无限循环
二、假如char是有符号类型:
- 假如getchar()读入字节0xFF
- 此时执行c=getchar(),发生类型转换(int—>signed char),0x000000FF截取高24位后,c=0xFF
- 执行判断c!=EOF,发生类型转换(signed char—>int),有符号数c(0xFF)符号位扩展为0xFFFFFFFF(-1),此时c==EOF,跳出循环
因此若char是有符号类型则有可能会提前结束读取操作