Comparing unsigned char and EOF

Amol Sharma picture Amol Sharma · Dec 21, 2011 · Viewed 10.4k times · Source

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.

Answer

bashrc picture bashrc · Dec 21, 2011

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 .