EOF is an integer and is equal to -1. So if c is unsigned char, when you read at EOF it will be set to 0xff, which when upcast to an integer for the comparison with EOF will be converted to 0x000000ff and so the comparison will never evaluate FALSE, hence the infinite loop. However, when it is a (signed) char, upcasting 0xff will be sign-extended and result in 0xffffffff, which will equal EOF.

At a guess, the program bails out when it encounters an 0xff character, which is not the same thing as EOF. So it's better to use the feof() function that tests whether or not you are really at the end of the file.

Also as the file is binary you should open it in mode "rb" otherwise it defaults to text-mode, which means you might get some funky (and unwanted) conversions with values 10 and 13.