Amo*_*rma 7 c comparison eof unsigned-char fgetc
当编译以下代码时,它进入无限循环:
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;
}
Run Code Online (Sandbox Code Playgroud)
gcc编译器也会在编译时发出警告
abc.c:13:warning: comparison is always true due to limited range of data type
Run Code Online (Sandbox Code Playgroud)
当代码unsigned char被替换为char或int按预期时,代码运行正常,即它终止.
但代码也运行unsigned int良好.因为我有我读的EOF就是定义为-1在stdio.h那为什么此代码为无符号的字符失败,但运行良好的unsigned int类型.
写这条线的黄金法则是
while ((ch = fgetc(stdin)) != EOF)
Run Code Online (Sandbox Code Playgroud)
ch应该是int.你使用ch无符号的可爱技巧失败,因为它EOF是一个有符号的int数量.
好的,我们现在进入深度......
步骤1:
ch=fgetc(fp)
Run Code Online (Sandbox Code Playgroud)
fgetc()返回-1(签名int).通过C的黄金法则ch获得最后一个八位位数1.因此价值255.ch执行后的字节模式
ch = fgetc(fp);
Run Code Online (Sandbox Code Playgroud)
因此会
11111111
Run Code Online (Sandbox Code Playgroud)
第2步:
ch != EOF
Run Code Online (Sandbox Code Playgroud)
现在EOF是一个有 符号整数,ch是unsigned char...
我再次提到C的黄金法则...... 在比较之前,较小的家伙ch被转换为大尺寸int,所以现在它的字节模式
00000000000000000000000011111111 = (255)10
Run Code Online (Sandbox Code Playgroud)
虽然EOF是
11111111111111111111111111111111 = (-1)10
Run Code Online (Sandbox Code Playgroud)
它们无法平等.......因此,引导以下while循环的语句
while ((ch = fgetc(stdin)) != EOF)
Run Code Online (Sandbox Code Playgroud)
永远不会评价为假......
因此无限循环.
有几个隐式转换正在进行中.它们与特定警告并不真正相关,但我将它们包含在这个答案中,以显示编译器对该表达式的真正作用.
所以表达式相当于
(unsigned char)ch != (int)EOF
Run Code Online (Sandbox Code Playgroud)
C中的整数提升规则将隐式地将unsigned char转换为unsigned int:
(unsigned int)ch != (int)EOF
Run Code Online (Sandbox Code Playgroud)
然后,C中的平衡规则(也就是通常的算术转换)将隐式地将int转换为unsigned int,因为每个操作数必须具有相同的类型:
(unsigned int)ch != (unsigned int)EOF
Run Code Online (Sandbox Code Playgroud)
在你的编译器EOF可能是-1:
(unsigned int)ch != (unsigned int)-1
Run Code Online (Sandbox Code Playgroud)
假设32位CPU,它与...相同
(unsigned int)ch != 0xFFFFFFFFu
Run Code Online (Sandbox Code Playgroud)
角色永远不会有这么高的价值,因此警告.
| 归档时间: |
|
| 查看次数: |
8742 次 |
| 最近记录: |