比较 unsigned char 和 EOF
当编译以下代码时,它会进入无限循环:
int main()
{
unsigned char ch;
FILE *fp;
fp = fopen("abc","r");
if(fp==NULL)
{
printf("Unable to Open");
exit(1);
}
while((ch = fgetc(fp))!=EOF)
printf("%c",ch);
fclose(fp);
printf("\n",ch);
return 0;
}
gcc 编译器还会在编译时发出警告,
abc.c:13:warning: comparison is always true due to limited range of data type
当 unsigned char
被 char
或 替换时,代码运行良好int
正如预期的那样,它终止。
但该代码对于 unsigned int
也运行良好。 正如我所读到的, EOF
在 stdio.h
中定义为 -1
那么为什么这段代码对于 unsigned char 失败但运行良好对于无符号整数。
when the following code is compiled it goes into an infinite loop:
int main()
{
unsigned char ch;
FILE *fp;
fp = fopen("abc","r");
if(fp==NULL)
{
printf("Unable to Open");
exit(1);
}
while((ch = fgetc(fp))!=EOF)
printf("%c",ch);
fclose(fp);
printf("\n",ch);
return 0;
}
The gcc Compiler also gives warning on compilation
abc.c:13:warning: comparison is always true due to limited range of data type
the code runs fine when unsigned char
is replaced by char
or int
as expected i.e. it terminates.
But the code also runs fine for unsigned int
as well.
as i have i have read in EOF
is defines as -1
in stdio.h
then why does this code fails for unsigned char but runs fine for unsigned int.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
编写此行的黄金法则是
ch
应该是int
。使ch
无符号的可爱技巧失败了,因为EOF
是一个有符号 int 数量。好吧,现在让我们深入探讨......
第 1 步:
fgetc()
返回-1
(一个带符号的int
)。根据 C 的黄金法则,ch
获取最后一个八位字节,全部为1
。因此值为255
。执行后ch
的字节模式将是
步骤2:
现在
EOF
是一个有符号整数并且ch
是一个unsigned char
...我再次参考 C 的黄金法则...较小的家伙
ch
转换为大尺寸int
在比较之前,所以它的字节模式现在是,而
EOF
是他们不可能相等......因此引导以下 while 循环的语句
永远不会计算为 false ...
因此是无限循环。
The golden rule for writing this line is
ch
should beint
.Your cute trick of makingch
unsigned fails becauseEOF
is a signed int quantity.Ok, let's now go into the depth......
Step 1:
fgetc()
returns-1
(a signedint
). By the golden rules of Cch
gets the last octet of bits which is all1
's. And hence the value255
. The byte pattern ofch
after the execution ofwould thus be
Step 2:
Now
EOF
is a signed integer andch
is anunsigned char
...Again I refer to the golden rule of C ... the smaller guy
ch
is converted to big sizeint
before comparision so its byte pattern is nowwhile
EOF
isThere is no way they can be equal....... Hence the statement to steer the following while-loop
will never evaluate to false ...
And hence the infinite loop .
有几个隐式转换正在进行。它们与特定警告并不真正相关,但我将它们包含在这个答案中以显示编译器对该表达式的真正作用。
因此,该表达式相当于
C 中的整数提升规则将隐式地将 unsigned char 转换为 unsigned int:
然后 C 中的平衡规则(又名通常的算术转换)将隐式将 int 转换为 unsigned int,因为每个操作数必须具有相同的类型:
在您的编译器上 EOF 可能是 -1:
假设 32 位 CPU,它与 A 字符永远不会有如此高的值相同
,因此 警告。
There are several implicit conversions going on. They aren't really relevant to the specific warning, but I included them in this answer to show what the compiler really does with that expression.
So the expression is equivalent to
The integer promotion rules in C will implicitly convert the unsigned char to unsigned int:
Then the balancing rules (aka the usual arithmetic conversions) in C will implicitly convert the int to unsigned int, because each operand must have the same type:
On your compiler EOF is likely -1:
which, assuming 32-bit CPU, is the same as
A character can never have such a high value, hence the warning.
我也遇到过这个问题。我的解决方案是使用 feof()。
您可以定义一个 int 变量来与 EOF 进行比较。例如:
这对我有用。
**重要更新***
之后使用我之前提到的方法,我发现了一个严重的问题。
feof() 不是打破 while 循环的好方法。
原因如下。 http://www.gidnetwork.com/b-58.html
所以我找到了一个更好的方法来做到这一点。我使用 int 变量来做到这一点。这里:
经过我的测试,这是有效的。
I have encountered this problem too. My solution is to use feof().
And you can define an int variable to compare with EOF. For example:
This works for me.
**IMPORTANT UPDATE***
After using the method I mentioned before, I found a serious problem.
feof() is not a good way to break the while loop.
Here is the reason for it. http://www.gidnetwork.com/b-58.html
So I find a better way to do this. I use an int variable to do it. here:
After my test, this works.
您需要使用 int
fgetc() 专门返回一个 int ,以便它可以指示文件结尾
,它可以使用有符号的 char 运行良好,因为 EOF (-1) 在范围内,但如果您使用 char 读取它会中断值大于 127。
使用 int,在检查 EOF 后将其转换为 char
you need to use an int
fgetc() returns an int specifically so that it can indicate the end of file
it runs fine with signed char because EOF (-1) is in the range, but it would break if you read in a char with value greater than 127.
Use an int, cast it to a char after you've checked for EOF
当您将无符号整型与有符号整型进行比较时,它将有符号整型转换为无符号整型并进行比较。因此,当您使用 unsigned int 'ch' 读取文件时,读取 EOF 会为您提供 2^32+1 (在 4 字节 int 机器上),并且当将其与 EOF 进行比较时,它将 EOF 转换为 unsigned,这也是 2^ 32+1,因此程序停止!
如果您使用 unsigned char ch,当您读取文件时,读取 EOF 返回 2^32+1,并且这将被转换为 unsigned char,这会将值截断为前 8 位(在 1 字节字符机器上)并给出您输出为 255。因此,您正在比较 255 和 2^32+1,从而导致无限循环。
这里的问题是比较之前截断。
如果你使用
你的程序将运行良好!
When you compare an unsigned int with a signed int, it converts the signed int to unsigned int and compares them. Hence when you are reading the file with an unsigned int 'ch', reading an EOF gives you 2^32+1 (on a 4 byte int machine) and when comparing it with EOF, it converts EOF to unsigned which is also 2^32+1 and hence the program stops!
If you use unsigned char ch, when you read the file, reading EOF returns 2^32+1, and this will be casted to unsigned char, which truncates the value to first 8 bits (on a 1 byte char machine) and gives you an output of 255. Hence you are comparing 255 and 2^32+1, causing an infinite loop.
The problem here is truncating before compare.
If you use
you program will run fine!
这种实现方式会产生 lint 警告
FIX 进行比较:
a lint warning is produced with this kind of implementation
FIX: