by Hammer ,ljbsdu译
EOF的使用以及意义看起来给新手程序员带来了不少困惑,希望这个解释能够帮助你更好的理解它。在深入的解释EOF是什么之前,我先告诉你EOF不是什么。
EOF不是:
1、一个字符;
2、一个存在于文件结尾的值;
3、一个可以存在于文件中间的值;
那它究竟是什么呢?
EOF是一个定义为负值的int型的宏。它通常用来作为进行读操作的函数的返回值,标志读操作错误或者到达输入的结尾。因为变量提升规则(稍后详细讨论),你必须谨记使用int变量来保存这些(读)函数的返回值,即使函数的返回值看起来是char,例如getchar()或fgetc();
下面是一些你可能用到的代码例子:
char到int的提升
根据定义,int表示的值比char大,所以一个负值的int绝不可能容纳与char相同的值(??)。但是,当你比较一个int和char时,char类型将会提升成为int型,以此来解释(?)变量在所占位数上的差异。char提升后的值受到它的符号的影响,不幸的是一个char变量既可以是有符号的也可以是无符号的,这取决于编译器。
为了更好的理解,让我们看一下一些int和char的代表性的数字。
下面假设int为2个字节(你的编译器可能会更多),char只使用1个字节(这个与你的编译器是一致的)。除了第一列,下面的值都是用16进制表示的。
从“char to int promotion”表可以很明显的看出char的符号导致产生不同的int值。
那么这些对一个程序员来说意味着什么?
嗯,让我们看一个上面的代码的修改版,这次我们将错误的使用一个char变量来保存fgetc()函数的返回值;
现在我们假设我们正在读取的是文件中的一个值为0xff的byte。fgetc()将以int型返回该值,所以它看起来应该是这样0x00 0xff(同样
,我假设一个int为2个字节)。为了在char中存储该值,char就必须降级,所以字节值就变为0xff。
然后,字节c与int型的EOF比较。提升规则起作用了,c必须提升为int型。但是在例子代码中,c的符号并没有显式的声明,所以我们并不知道它是有符号还是无符号的,所以提升后的int值可能为0xff 0xff也可能为0x00 0xff。所以代码并不保证按照我们的要求运行。
下面是一段小的程序帮助展示这种提升。
另一个需要考虑的情况是当char是无符号时。这种情况下,对fgetc()函数的返回值的降级或者提升的过程将会对EOF的值产生破坏作用,并且将会使程序陷入死循环。让我们看一下整个过程:
-----在fgetc()在到达输入结尾时返回EOF(0xff 0xff),然后被降级为0cff,放到一个无符号char变量c中,无符号的char c提升为int,值由0xff变为0xff 0xff,EOF与c比较,即0xff 0xff 与0x00 0xff之间的比较。结果为false(因为值不同),这并不是所期望的。fgetc()又一次被调用,仍然返回EOF,死循环开始了!
下面的代码演示了这个问题。