If you will write for example
char c;
c = getchar();
while (c != EOF) {
//...
when in the condition c != EOF the value of the object c is promoted to the type int and two integers are compared.
The problem with declaring the variable c as having the type char is that the type char can behave either as the type signed char or unsigned char (depending on a compiler option). If the type char behaves as the type unsigned char then the expression c != EOF will always evaluate to logical true.
Pay attention to that according to the C Standard EOF is defined the following way
EOF which expands to an integer constant expression, with type int and
a negative value, that is returned by several functions to indicate end-of-file, that is, no more input from a stream;
So after this assignment
c = getchar();
when c is declared as having the type char and the type char behaves as the type unsigned char then the value of c will be a positive value after the integer promotion and hence will not be equal to a negative value.
To simulate the situation just declare the variable c as having the type unsigned char
unsigned char c;