C
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions
-
Section 4: Arrays and Strings
-
Section 5: Pointers
-
Section 6: Memory Management
-
Section 7: Structures and Unions
-
Section 8: The Preprocessor and Build Process
-
Section 9: Standard Library: stdio.h
-
Section 10: Standard Library: stdlib.h
-
Section 11: Standard Library: string.h
-
Section 12: Standard Library: ctype.h and wctype.h
-
Section 13: Standard Library: math.h, complex.h, fenv.h, tgmath.h
-
Section 14: Standard Library: Type and Limit Headers
-
Section 15: Standard Library: Error Handling and Debugging
-
Section 16: Standard Library: Localization and Encoding
-
Section 17: Standard Library: time.h
-
Section 18: Standard Library: Concurrency (C11)
-
Section 19: POSIX and System Programming (unistd.h)
-
Section 20: More Data Structures
-
Section 21: Algorithms in C
-
Section 22: Bitwise Operations
-
Section 23: Command-Line Programs
-
Section 24: Debugging and Best Practices
-
Section 25: Compiler and Language Internals
-
Section 26: Embedded and Cross-Platform Considerations
-
Section 27: Networking Basics
-
Section 28: Practical Projects
-
Section 29: Interview Practice
-
Section 30: C23 Modern Features
-
Section 31: More Practice and Review
85: Buffering and fflush
Ever spent an hour debugging a segfault, only to realize your print statements were lying to you? It's a rite of passage in C. You put a printf("I am here!\n"); right before a suspicious line of code, the program crashes, and you look at the console only to see... nothing. You assume the crash happened before that line, so you waste your time searching the wrong part of the codebase.
Here is a classic example of this frustration. I've written a small loop that simulates processing some data, but it contains a deliberate memory error.
#include <stdio.h>
#include <stdlib.h>
int main() {
for (int i = 1; i <= 5; i++) {
printf("Processing record %d...", i);
// Simulate a crash on the 3rd record
if (i == 3) {
int *p = NULL;
*p = 10; // Segfault here
}
}
return 0;
}
The Mystery of the Missing Output
If you run this, you'll likely see nothing at all in your terminal before the "Segmentation fault" message appears. You might think the program crashed at record 1, or even before the loop started. But that's not what happened. The program actually reached record 3, but the text "Processing record 1...", "Processing record 2...", and "Processing record 3..." is still sitting in a memory buffer.
C's stdio library doesn't send every single character to the screen the moment you call printf. That would be incredibly slow because every system call to the OS has overhead. Instead, it uses a buffer—a temporary storage area in RAM. It waits until the buffer is full, or until it sees a newline character \n (this is called line-buffering), before it actually "flushes" that data to the terminal.
In my example above, I didn't use \n because I wanted a progress bar effect. When the program crashes, the process is killed instantly by the OS. The data sitting in that buffer is simply wiped away, never having reached your screen.
Forcing the Hand with fflush
To fix this, we need to tell C: "I don't care if the buffer isn't full and I don't care that there's no newline; send this data to the destination now." That's exactly what fflush() does.
#include <stdio.h>
#include <stdlib.h>
int main() {
for (int i = 1; i <= 5; i++) {
printf("Processing record %d...", i);
// Force the buffer to empty into the terminal
fflush(stdout);
if (i == 3) {
int *p = NULL;
*p = 10;
}
}
return 0;
}
Now, when you run the code, you'll see Processing record 1...Processing record 2...Processing record 3... printed clearly before the crash. By calling fflush(stdout), we ensured the output was physically written to the screen before the crash occurred.
You'll use this most often in two scenarios: when you're writing prompts that don't end in a newline (like printf("Enter your name: ");) to ensure the user actually sees the prompt before scanf pauses the program, or when writing logs to a file. If you're writing to a file via fprintf, a crash can lose several kilobytes of log data unless you flush periodically. Just don't call it inside a tight loop that runs millions of times, or you'll tank your performance by forcing a system call on every single iteration.
📋 Practical Task
Build a Real-Time Heartbeat Logger
Your task is to create a program that simulates a system "heartbeat." The program should write a timestamped message to a file named heartbeat.log every second to prove the system is still alive.
Requirements:
- Open a file called
heartbeat.logfor writing. - Use a loop that runs for 10 iterations.
- In each iteration, use
fprintfto write "Heartbeat pulse [number]..." to the file. - Crucially, use
fflush()after each write so that if someone runstail -f heartbeat.login another terminal, they see the pulses appearing in real-time rather than in one big chunk at the end. - Use
sleep(1)(from<unistd.h>on Unix or<windows.h>on Windows) to create the one-second delay. - Close the file properly at the end.
There are no comments for now.