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.
The golden rule for writing this line is
while ((ch = fgetc(stdin)) != EOF)
ch
should be int
.Your cute trick of making ch
unsigned fails because EOF
is a signed int quantity.
Ok, let's now go into the depth......
Step 1:
ch=fgetc(fp)
fgetc()
returns -1
(a signed int
). By the golden rules of C ch
gets the last octet of bits which is all 1
's. And hence the value 255
. The byte pattern of ch
after the execution of
ch = fgetc(fp);
would thus be
11111111
Step 2:
ch != EOF
Now EOF
is a signed integer and ch
is an unsigned char
...
Again I refer to the golden rule of C ... the smaller guy ch
is converted to big size int
before comparision so its byte pattern is now
00000000000000000000000011111111 = (255)10
while EOF
is
11111111111111111111111111111111 = (-1)10
There is no way they can be equal....... Hence the statement to steer the following while-loop
while ((ch = fgetc(stdin)) != EOF)
will never evaluate to false ...
And hence the infinite loop .