我试图逐位读取位图文件,并且有一个循环运行,直到到达EOF。为此,我有一个声明为unsigned int
的变量,用于存储每个字节。当此变量等于EOF
时,循环停止。
有趣的一点是:如果我将变量声明为unsigned int
,它将起作用。但是,如果我将变量声明为unsigned short int
,则循环将永远运行,因为它永远找不到EOF
。
#include <stdio.h>
int main()
{
FILE *file;
unsigned int currentByte;
file = fopen("/home/stanley/Desktop/x.bmp", "rb");
while ((currentByte = fgetc(file)) != EOF) {
printf("%d \n", currentByte);
}
fclose(file);
return 0;
}
上面的代码是我正在编写的代码。如果文件大小为90B,则会在屏幕上打印90个字节。
但是,由于某种原因,当我将其更改为unsigned short int currentByte
时,循环将永远运行。好像currentByte
从未等于EOF
。
我在某处读到EOF
包含负值(-1)。但是,如果EOF
为负数,为什么当我仅使用unsigned int
时它起作用,为什么当我使用unsigned short int
时它会出错?从理论上讲,问题不应该与unsigned
本身有关,而不是与short
有关吗?无法签名的人不能存储负值。
很抱歉,这是一个非常愚蠢的问题。我试图更好地理解位和字节的工作方式,有些概念对我来说可能还很陌生。
我正在以下环境中对其进行编译:
先谢谢了。 :)
答案 0 :(得分:3)
如果int
的大小大于short
的大小,那么您将遇到此问题。
我们假设EOF
的类型为int
,并包含值-1。为了举例说明,我们还假设int
是32位值,而short
是16位值。
在这种情况下,如果fgetc
返回EOF
,当作为unsigned int
时它将具有0xFFFFFFFF的值。将其与EOF
(类型int
)进行比较时,有符号整数-1将转换为无符号值0xFFFFFFFF。这两个值相等,因此比较可以按预期进行。
但是,由EOF
返回的fgetc
被视为unsigned short
,其值为0xFFFF。因为unsigned short
的大小小于int的大小,所以当将此值与EOF
进行比较时,unsigned short
0xFFFF将转换为值为0x0000FFFF的int
(为清楚起见,显示了额外的数字)。由于对于32位值,-1不等于0xFFFF,因此此比较始终不相等,并且循环不会停止。
fgetc
返回int
的事实提示您应将其保留为该类型,否则将丢弃某些信息或导致比较混乱。
答案 1 :(得分:2)
您应该使用类型int
来匹配fgetc
返回的内容,而不是unsigned int
。循环停止条件与unsigned int
一起工作的原因不是值永远为负,而是当!=
运算符与对象的unsigned
和signed
操作数一起使用时排名相同,都在比较之前被提升为unsigned
。将EOF
的{{1}}结果分配给fgetc
并将currentByte
提升为EOF
都会产生相同的结果,因此它们比较相等。
答案 2 :(得分:2)
当您将有符号整数转换为无符号整数时(将EOF
分配给无符号整数变量时会发生这种情况),通过加UINT_MAX + 1
将结果转换为无符号整数。因此,如果EOF
为-1
,则该值将变为UINT_MAX
。
并且UINT_MAX
仅适合unsigned int
而不适合unsigned short
。
并且这种特殊转换的结果是实现定义的,因此程序的行为将取决于它。
请注意,fgetc
函数将返回int
,因此必须使用int
变量来存储其值。