Skip to content
C Basics: Keep Byte Input Separate from EOF

C Basics: Keep Byte Input Separate from EOF

November 1, 2026

A byte with value 255 must not be mistaken for the end of a file. Keep the fgetc result in an int until after checking it against EOF.

Prepare a scratch directory

Tested on Linux amd64 with GCC 14.2.0. Install GCC and make gcc available on PATH. You also need Bash, a text editor, and the standard mktemp, rm, and rmdir utilities. This example uses the C standard library.

Keep the same terminal open. Stop if setup fails, before saving the source:

start_directory="$PWD"
work_directory="$(mktemp -d)" || exit 1
cd -- "$work_directory" || exit 1

Run the example

Save this as fgetc-eof-value-demo.c:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    FILE *stream = tmpfile();
    if (stream == NULL) {
        perror("tmpfile");
        return EXIT_FAILURE;
    }
    if (fputc(0xff, stream) == EOF || fputc('A', stream) == EOF ||
        fseek(stream, 0, SEEK_SET) != 0) {
        perror("prepare stream");
        fclose(stream);
        return EXIT_FAILURE;
    }
    int current_byte;
    size_t count = 0;
    while ((current_byte = fgetc(stream)) != EOF) {
        printf("Byte: %u\n", (unsigned int)current_byte);
        ++count;
    }
    int failed = ferror(stream) != 0;
    printf("Count: %zu; error: %d\n", count, failed);
    if (fclose(stream) != 0) {
        perror("fclose");
        return EXIT_FAILURE;
    }
    return failed ? EXIT_FAILURE : EXIT_SUCCESS;
}

Compile and run it. The second command runs only after compilation succeeds:

gcc -std=c17 -Wall -Wextra -Werror -pedantic fgetc-eof-value-demo.c -o fgetc-eof-value-demo &&
./fgetc-eof-value-demo

Observed output:

Byte: 255
Byte: 65
Count: 2; error: 0

Read the result

On this Linux system, the loop prints 255 and 65, then stops at EOF. fgetc returns an unsigned-char value converted to int on success. The int variable keeps that value separate from the negative EOF sentinel. The error indicator is checked after the loop.

Apply it carefully

Assigning the result to char first loses information: a signed char can turn 255 into -1, and an unsigned char cannot retain the negative EOF sentinel. This loop reads bytes, not Unicode characters. The example assumes the usual eight-bit Linux bytes and creates no persistent data file.

The official reference documents the behavior used here.

Clean up

Remove only the source and executable created for this example, then return to the starting directory:

rm -- fgetc-eof-value-demo.c fgetc-eof-value-demo
cd -- "$start_directory" || exit 1
rmdir -- "$work_directory"
unset start_directory work_directory

If the directory is not empty, inspect its remaining contents before removing anything else.

Acknowledgements

This post was created with assistance from AI.

Last updated on