Exercise 1-6. Verify that the expression
getchar() != EOFis 0 or 1.
What This Exercise Is Really About
This is not a “write a loop” exercise — it is a verification exercise, and the thing being verified is a fundamental rule of C that surprises many beginners: every relational expression in C evaluates to an integer, specifically 0 (false) or 1 (true). There is no boolean type in C89; the language has always used integers as truth values.
When you write while ((c = getchar()) != EOF), the != operator does not produce some abstract “true/false” — it produces the integer 1 while there are characters to read, and the integer 0 when EOF is reached. Understanding this removes the mystery from every loop condition you will ever write in C.
Verification Program
The cleanest proof is to pass the expression directly to printf with the %d format, which prints it as an integer:
/* Compile: gcc -ansi -Wall ex1-6.c -o ex1-6 */
#include <stdio.h>
int main(void)
{
printf("getchar() != EOF evaluates to: %d\n", getchar() != EOF);
return 0;
}
Run this twice to see both values. First, type a character and press Enter:
$ ./ex1-6 A getchar() != EOF evaluates to: 1
Second, send EOF immediately with Ctrl+D (Linux/macOS) or Ctrl+Z then Enter (Windows):
$ ./ex1-6 ^D getchar() != EOF evaluates to: 0
The relational expression produces 1 when a character is available and 0 when EOF is reached. Exactly 0 or 1. Nothing else.
A Demonstration That Shows Both Cases at Once
To see both values in a single run, read one character from stdin and then evaluate the same expression against the literal EOF:
/* Compile: gcc -ansi -Wall ex1-6b.c -o ex1-6b */
#include <stdio.h>
int main(void)
{
int c;
c = getchar();
printf("After reading a character: (c != EOF) = %d\n", c != EOF);
printf("When c equals EOF: (EOF != EOF) = %d\n", EOF != EOF);
printf("EOF value on this system: %d\n", EOF);
return 0;
}
$ ./ex1-6b A After reading a character: (c != EOF) = 1 When c equals EOF: (EOF != EOF) = 0 EOF value on this system: -1
This makes the two outcomes concrete: the expression is 1 while characters exist, and 0 at end-of-file.
The C Rule: Relational Operators Always Yield 0 or 1
The C standard (section 6.5.8 in C99, equally true in C89) states that relational and equality operators produce the value 1 if the comparison is true, and 0 if false, with type int. This covers all six operators:
==and!=(equality)<,>,<=,>=(relational)
So 3 > 2 is 1. 5 == 7 is 0. And getchar() != EOF is either 1 or 0. You can pass these expressions anywhere an integer is expected: to printf with %d, assign them to an int variable, or use them in arithmetic.
What is EOF and Why Does It Have the Value -1?
EOF is a macro defined in <stdio.h>. The C standard requires only that it be a negative integer constant — it is not required to be -1 specifically, but on every common system (Linux, macOS, Windows) it is -1.
Why negative? Because getchar() must be able to return every valid character value (0 through 255 on most systems) plus a distinct signal meaning “no more input.” If EOF were 0, it would collide with the null character '\0'. Making it negative keeps it out of the range of any unsigned byte value.
Why getchar() Returns int, Not char
This is the most important concept in the entire exercise. getchar() is declared as:
int getchar(void);
Not char getchar(void). The return type must be int because the function needs to represent 257 distinct values: the 256 possible byte values (0–255) plus EOF (-1). A char can only hold 256 values — not enough.
The Classic Beginner Bug: Storing getchar() in a char
Many beginners write code like this:
char c; /* BUG: should be int */
while ((c = getchar()) != EOF) {
putchar(c);
}
This is wrong in two ways, depending on whether char is signed or unsigned on your platform:
If char is unsigned (common on ARM, some MIPS targets): getchar() returns -1 for EOF. Assigning -1 to an unsigned char wraps it to 255 (for an 8-bit char). Then the comparison becomes 255 != -1, which is 1 (true), so the loop never terminates at EOF. This is an infinite loop.
If char is signed (common on x86/x64): EOF (-1) stored in a signed char gives -1, which compares equal to EOF correctly. The loop terminates. However, any character with byte value 255 (such as ÿ in Latin-1) also becomes -1 when stored in a signed char, so it gets mistaken for EOF and terminates the loop prematurely.
The fix is always the same: declare c as int:
int c; /* correct */
while ((c = getchar()) != EOF) {
putchar(c);
}
How This Connects to the K&R Character-Counting Loop
In Chapter 1, K&R present the character-counting program:
#include <stdio.h>
int main(void)
{
long nc;
nc = 0;
while (getchar() != EOF)
++nc;
printf("%ld\n", nc);
return 0;
}
Exercise 1-6 is placed right before this loop is used extensively. The authors want you to understand that getchar() != EOF is not magic — it is a plain integer expression that evaluates to 1 (keep looping) or 0 (stop). The while statement tests this integer exactly as it would test any other condition. Once you see the 1 and 0 printed with %d, the loop becomes transparent.
Compile and Run
gcc -ansi -Wall ex1-6.c -o ex1-6
./ex1-6
To send EOF from the keyboard: press Ctrl+D on Linux/macOS, or Ctrl+Z then Enter on Windows.
What This Exercise Teaches
- In C, all relational operators (
!=,==,<,>,<=,>=) produce the integer1(true) or0(false) — never any other value EOFis a negative integer constant (typically-1) defined in<stdio.h>, distinct from all valid character valuesgetchar()must returnint— notchar— so it can carry both all byte values (0–255) and the out-of-range EOF signal- Storing
getchar()‘s return value in acharis a classic portability bug that causes infinite loops on unsigned-char platforms
Set Up Your C Environment
To compile and run this solution, you need GCC installed. If you haven’t set up C on your machine yet:
- Complete C Development Environment Setup — start here if you’re new
- Install GCC on Windows 11
- Install GCC on macOS
- Install GCC on Ubuntu/Linux
- VS Code for C Programming — recommended editor
← Exercise 1-5 |
Chapter 1 Solutions |
Exercise 1-7 →
Book:
The C Programming Language, 2nd Ed — Kernighan & Ritchie