fgetc函数的返回值赋值给int变量,不能赋值给char,unsigned char变量

本文深入解析EOF宏定义及fgetc函数的工作原理,强调在读取文件时使用int类型变量接收fgetc函数返回值的重要性,避免char类型可能引发的错误。通过实例演示不同数据类型在比较时的潜在问题。

1、前言

EOF其实就是一个宏

#define EOF (-1)

即EOF 的值是占4个字节int,值为0xffffffff;

int fgetc(FILE *stream);     //从文件中读字符file get char    

成功返回读到的字符,

失败或者读到文件末尾返回EOF;

fgetc函数的返回值是int,此时

取值范围是:0x00 00 00 00 -----0x00 00 00 FF.

读到文件尾:EOF(0xFF FF FF FF)

int ch;	 //这个地方一定要是int才行!!!!!
while ( ( ch= fgetc(fp) ) != EOF)  //不断读取文件直到结束
{
	putchar(ch);
}

2、原因分析:

fgetc() 的返回值类型为 int,故要赋值给int类型变量,而不能赋值给char或unsigned char 类型变量?

假设fgetc取的字节是0xff,即返回值是0x000000ff;

1)若是char ch;

while ( ( ch= fgetc(fp) ) != EOF) 

是将int类型数据赋值给了char类型,只取后8位,故ch=0xff;

然后,ch与EOF比较,char类型与int类型比较,char会被转化为int,最终 ch变为0xffffffff,与EOF相等,函数退出,误以为到了文件结尾,造成错误。

0x00 00 00 FF------->0x FF--------->0xFF FF FF FF  与-1的编码冲突,会将0xFF 误认为是文件尾。

2)若是unsigned char ch;

while ( ( ch= fgetc(fp) ) != EOF) 

0xFF FF FF FF------->0x FF--------->0x00 00 00 FF  与-1(0xFF FF FF FF)不等,即:即使到了文件尾,也与EOF不等。

unsigned char 范围为0-255,文件末尾也无法得到-1,循环不会退出。

3)若是 int ch;

while ( ( ch= fgetc(fp) ) != EOF) 

返回值是0x000000ff,赋值给int ch,仍然是0x000000ff,不等于0xffffffff.能正确识别文件末尾。

文件中字符取值范围是:0x00 00 00 00 -----0x00 00 00 FF.

读到文件尾:EOF(0xFF FF FF FF)

不会出现问题。

举例,加深理解:

#include <stdio.h>
int main()
{
    int iret = 0xff;
    char cret = 0xff;
    int num = -1;
    printf("iret=%x\n",iret);
    printf("cret=%x\n",cret);
    printf("num=%x\n",num);
    if(iret!=num)
        printf("int:iret!=num\n");
    else
        printf("int:iret==num\n");
    if(cret!=num)
        printf("char:cret!=num\n");
    else
        printf("char:cret==num\n");
}

 

3、总结:

问题的关键是char 类型的数据与int型数据比较的时候,会被强转成int型的32位数据;

而int型数据与int型数据比较则不存在强制位数的转换。

char ch;

while ( ( ch= fgetc(fp) ) != EOF) 

是int  转char ;char 转 int------>值发生了变化

0x000000ff    -> 0xff  --> 0xffffffff

值由255-------->-1 ------------>-1

 

其实,不光是字符间的比较,char类型赋值给int型变量,也会出现这个问题:

 

也就是说:一个字节的-1,转换成4个字节的-1,是由0xff转换成0ffffffff,而不是转换成0x000000ff(这个不是-1了,而是255了

小转大,对结果不会产生影响,大转小,对结果会有影响,具体参见本文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值