您的位置:首页 > Web前端

EOF的定义与有效使用(Definition of EOF and how to use it effectively )

2011-03-22 15:29 513 查看
原文:http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1048865140&id=1043284351&utm_source=newletter&utm_medium=email&utm_campaign=twentyeight-followup

       by Hammer ,ljbsdu译

      EOF的使用以及意义看起来给新手程序员带来了不少困惑,希望这个解释能够帮助你更好的理解它。在深入的解释EOF是什么之前,我先告诉你EOF不是什么。
EOF不是:
1、一个字符;
2、一个存在于文件结尾的值;
3、一个可以存在于文件中间的值;
那它究竟是什么呢?
       EOF是一个定义为负值的int型的宏。它通常用来作为进行读操作的函数的返回值,标志读操作错误或者到达输入的结尾。因为变量提升规则(稍后详细讨论),你必须谨记使用int变量来保存这些(读)函数的返回值,即使函数的返回值看起来是char,例如getchar()或fgetc();

下面是一些你可能用到的代码例子:
int c;

while ((c = fgetc(fp)) != EOF)
{
putchar (c);
}


int ch;

while ((ch = cin.get()) != EOF)
{
cout <<(char)ch;
}

char到int的提升
      根据定义,int表示的值比char大,所以一个负值的int绝不可能容纳与char相同的值(??)。但是,当你比较一个int和char时,char类型将会提升成为int型,以此来解释(?)变量在所占位数上的差异。char提升后的值受到它的符号的影响,不幸的是一个char变量既可以是有符号的也可以是无符号的,这取决于编译器。
 为了更好的理解,让我们看一下一些int和char的代表性的数字。

下面假设int为2个字节(你的编译器可能会更多),char只使用1个字节(这个与你的编译器是一致的)。除了第一列,下面的值都是用16进制表示的。
 
-----------------------------        ------------------------------
|  char and int comparison  |        |     char to int promotion  |
-----------------------------        ------------------------------
| Decimal |  int    |  char |        |  char | unsigned | signed  |
|---------|---------|-------|        |-------|----------|---------|
|  2      |  00 02  |  02   |        |  02   |  00 02   |  00 02  |
|  1      |  00 01  |  01   |        |  01   |  00 01   |  00 01  |
|  0      |  00 00  |  00   |        |  00   |  00 00   |  00 00  |
| -1      |  FF FF  |  FF   |        |  FF   |  00 FF   |  FF FF  |
| -2      |  FF FE  |  FE   |        |  FE   |  00 FE   |  FF FE  |
-----------------------------        ------------------------------
 

从“char to int promotion”表可以很明显的看出char的符号导致产生不同的int值。

那么这些对一个程序员来说意味着什么?
嗯,让我们看一个上面的代码的修改版,这次我们将错误的使用一个char变量来保存fgetc()函数的返回值;

char c;

while ((c = fgetc(fp)) != EOF)
{
putchar (c);
}


      现在我们假设我们正在读取的是文件中的一个值为0xff的byte。fgetc()将以int型返回该值,所以它看起来应该是这样0x00 0xff(同样

,我假设一个int为2个字节)。为了在char中存储该值,char就必须降级,所以字节值就变为0xff。
      然后,字节c与int型的EOF比较。提升规则起作用了,c必须提升为int型。但是在例子代码中,c的符号并没有显式的声明,所以我们并不知道它是有符号还是无符号的,所以提升后的int值可能为0xff 0xff也可能为0x00 0xff。所以代码并不保证按照我们的要求运行。
 下面是一段小的程序帮助展示这种提升。
 
#include <stdio.h>

int main(void)
{
int i = -1;
signed char sc = 0xff;
unsigned char usc = 0xff;

printf ("Comparing %x with %x/n", i, sc);
if (i == sc)    puts("i == sc");
else            puts("i != sc");
putchar ('/n');
printf ("Comparing %x with %x/n", i, usc);
if (i == usc)   puts("i == usc");
else            puts("i != usc");

return 0;
}

/*
* Output

Comparing ffff with ffff     <--- Notice this has been promoted
i == sc

Comparing ffff with ff
i != usc

*
*/
 
      另一个需要考虑的情况是当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,死循环开始了!

 下面的代码演示了这个问题。
#include <stdio.h>

int main(void)
{
FILE *fp;
unsigned char c;

if ((fp = fopen("myfile.txt", "rb")) == NULL)
{
perror ("myfile.txt");
return 0;
}

while ((c = fgetc(fp)) != EOF)
{
putchar (c);
}

fclose(fp);
return 0;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  编译器 fp c output byte null
相关文章推荐