You need a handle to touch data on disk. In C, that handle is a pointer returned by fopen. You specify a mode, get back a pointer, and use it to stream data in or out. The most common modes are r for reading, w for writing, and a for appending. Get them wrong, and you might lose data or crash your program.
Consider a simple task: writing the numbers 1 through 10 to a file.
This code opens a file named out using the w mode. This is a destructive write. If out doesn’t exist, the system creates it. If it does exist, the old content is wiped clean and replaced. The variable f holds the file pointer. You use this pointer for all subsequent operations. If the file cannot be opened—permissions issues, disk full, or path doesn’t exist—f becomes NULL.
The output function here is fprintf. It works exactly like printf, but you pass the file pointer as the first argument. Once you are done, fclose releases the resource.
Handling File Errors in Main
This snippet is the first in the series to return an error code from main. When fopen fails, f contains a null value. In C, zero evaluates to false. Everything else is true. The ! operator inverts that boolean logic.
if (!f) checks if the pointer is null. It is equivalent to if (f == 0), but the former is the standard idiom. If the condition is true, the program returns 1.
On UNIX systems, you can check this exit status directly from the command line. It tells you whether the script or program ran successfully or hit a wall. Knowing how to catch these errors early saves hours of debugging later.
Why do we bother with return codes when we could just crash? Because controlled failure is better than undefined behavior. You can log the error, notify the user, or retry. Letting the program die silently is lazy engineering.
The beauty of this approach lies in its simplicity. You open. You check. You write. You close. No magic. No hidden state. Just a pointer and a file.
But what if you need to read what you just wrote? Or append to an existing log without destroying history? The mode string changes everything. r leaves the file alone. a adds to the end. w blows it away. Choose carefully.

















