Reputation: 80
So I was writing a program on my Raspberry Pi Zero to count the frequencies of different word lengths in the input, but the program didn't stop at EOF.
So I tried this to debug:
#include <stdio.h>
#include <stdlib.h>
void main() {
char c;
while ( (c = getchar()) != EOF) {
putchar(c);
}
}
And compiled with this:
gcc test.c && ./a.out <input.txt
It printed out the input text, but then just kept printing question marks until I hit Ctrl+C. When I copied the program over onto my laptop and ran it there, everything worked fine.
I could just finish on the laptop, but I'm curious. Why can't the Pi detect when the file hit EOF?
Upvotes: 3
Views: 326
Reputation: 409176
First couple of facts:
EOF
is a macro that expands to the integer constant -1
. This integer constant will have the type int
.char
is signed or unsigned. The same compiler on different platforms might have different char
implementations.Now for the long explanation about your problem:
When integer types of different sizes are used in arithmetic expressions (and comparison is considered an arithmetic operator), then both operands of the expression undergoes usual arithmetic conversion to get a common type (usually int
).
For smaller integer types, like for example char
, that involves integer promotion to convert it to an int
. For this promotion the value of the char
needs to be kept intact, so e.g. -1
as a char
will still be -1
as an int
.
Because of how negative numbers are represented on most systems, the char
value of -1
is (in hexadecimal) 0xff
. For a signed char
, when -1
is converted to an int
, it keeps the value -1
(which will be represented as 0xffffffff
for a 32-bit int
type).
The problem comes when char
is unsigned, because then when getchar
returns EOF
(the value -1
) the unsigned char
value will be equal to 255
(the unsigned decimal representation of 0xff
). And when promoted to an int
the value will still be 255
. And 255 != -1
!
That's why the getchar
return type is int
and not char
. And one of the reason why all character-handling functions are using int
instead of char
.
So to solve your problem, you need to change the type of the variable c
to int
:
int c;
Then it will work
Upvotes: 4
Reputation: 15793
getchar's return value
is supposed to be able to return any ASCII (and extended ASCII) character between 0 and 255.
In order to make the distinction between an ascii and EOF, EOF cannot be a value in this interval, so getchar's return type must have more than 8 bits.
int getchar(void);
So you should write
int c;
while ( (c = getchar()) != EOF) ...
Upvotes: 1
Reputation: 7257
getchar
returns int
value not char
value. Since you need some way to recognise in one getchar
function if you read regular character or if function tells you there is nothing more to read - someone long time ago decided to use int
so that some value bigger than char
can be returned to indicate end of file. Change char
to int
.
Upvotes: 2