3 ms·
> Hint: it relies on implementation-defined behavior I don’t think so. fgetc returns an int (https://en.cppreference.com/w/c/io/fgetc https://en.cppreference.
by Someone 3y ago
> Hint: it relies on implementation-defined behavior
I don’t think so.
fgetc returns an int (https://en.cppreference.com/w/c/io/fgetc https://en.cppreference.com/w/c/io/fgetc) and EOF is an int (https://en.cppreference.com/w/c/io https://en.cppreference.com/w/c/io)
So,
*ptr = fgetc(src);
discards part of the result of fgetc.
If my C isn’t too rusty, that means the code can’t discriminate between hitting end of file and reading some byte value from the files (AFAIK EOF is -1 on most systems, so that value would often be 0xFF)
- jcranmer 3y agoEOF being -1 means that if (*ptr == EOF) can never fire if *ptr can only take on the values 0..255 [i.e., char is unsigned] as opposed to -128..127 [i.e., char is signed]. Whether or not char is signed or unsigned is implementation-defined.
- boywitharupee 3y agoThis is interesting and I'm curious how is this being solved in the wild? I'm on an ARM (m1 mac) machine and looks like char type is a signed type. EOF on this machine is -1 1. How can you distinguish between the char in the file and EOF (-1)? 2. Is EOF reserved for all files on macOS?
- comex 3y agoWhen fgetc succeeds, the int it returns has a value based on interpreting the byte as an unsigned char. On a platform with an 8-bit char, that means it’s in the range 0 to 255. This is required by the C spec regardless of whether char is signed or unsigned. Meanwhile, EOF is required to be negative. Thus, you can always distinguish the cases as long as you look at the original int return value rather than casting to char. Fun fact: This approach causes trouble on obscure embedded platforms where char and int are the same size (and therefore an unsigned char value can’t fit inside a signed int). Such platforms are allowed by the C standard as freestanding implementations that don’t implement the full standard library, but they can’t conformantly implement fgetc. https://stackoverflow.com/questions/3860943/can-sizeofint-ever-be-1-on-a-hosted-implementation https://stackoverflow.com/questions/3860943/can-sizeofint-ev...
- jcranmer 3y agoEvery byte in a file, as represented in an int, takes on a value of 0..255. fgetc doesn't return a char, it returns an int, which means it returns a value of -1..255 (i.e., 257 possible values). If you try to represent the return value of fgetc as a char, two of those values get the same representation, namely 255 and -1. The difference between ARM and x86 is that on ARM (unsigned char), the -1-as-255 is represented as 255 when cast back to an int for comparison, whereas on x86, the 255 when cast back to an int is -1, so it would return the same value as EOF (although it would also do so had the value in the file originally been -1). Representing binary data as unsigned char (as opposed to char or signed char) is the norm however.
- Gibbon1 3y agoSolve in the wild by never clipping the output of things like fgets() int ch = fgetc(src); if(ch == EOF) goto oops_eof; out++; *ptr++ = ch; *ptr = '\0'; if(strchr(s, ch)) return out; or maybe int ch; if((ch = fgetc(src)) == EOF) goto oops_eof; *ptr[out++] = ch; *ptr[out] = '\0'; if(strchr(s, ch)) return out;