🇯🇵 日本語 | 🇺🇸 English

Lesson 17: Debugging Techniques

How to debug C programs, with practical coverage of printf debugging and common bugs.

📖 What you'll learn on this page
✅ Must-know essentials
  • Use printf to inspect values
  • Pay attention to warnings: gcc -Wall -Wextra
  • Fix errors starting from the first one reported
⭐ Read if you have time
  • Interactive debugging with gdb
  • Sanitizers (-fsanitize=address,undefined)
  • Static analysis (cppcheck, etc.)

What is Debugging — The Art of Finding and Fixing Bugs

When a program doesn't work as expected, debugging is the process of finding and fixing the cause. Because C is a compiled language, bugs fall into two broad categories.
Compile errors
The code won't compile because of syntax mistakes. Compiler messages are your main clue.
Runtime bugs
The code compiles but produces wrong results or crashes. Track these down with printf debugging.

Basic debugging steps

🔍
1. Reproduce
Identify when the bug occurs
📍
2. Locate
Narrow it down with printf
🤔
3. Hypothesize
Ask why it's wrong
🛠️
4. Fix & verify
Retest after fixing
Important: Don't patch the "probably the problem" spot — always confirm the root cause before fixing. Guess-fixes introduce new bugs.

Reading Compile Errors

gcc error messages follow the form filename:line:col: error: message. The key is to fix the first error first.

Common compile errors

error: expected ';' before '}' token
Cause: A missing semicolon ;. Check the line before the one reported.
int x = 10   // ← no ; !
printf("%d", x);
error: 'pritnf' was not declared in this scope
Cause: A misspelled function name (pritnf → printf) or a missing #include.
error: 'x' undeclared (first use in this function)
Cause: The variable was never declared, or it's being used outside its scope.
warning: format '%d' expects argument of type 'int'
Cause: The format specifier doesn't match the argument type — for example, %d used where a double needs %f.
Tip: Don't panic if you see a long list of errors. Fixing the first one often makes many of the others disappear at once.

printf Debugging — The Easiest Technique

Use printf to print variable values or "reached here" markers and trace your program's behavior. It's the simplest technique beginners can put to use right away.

Techniques

// Technique 1: print variable values
printf("DEBUG: x=%d, y=%d\n", x, y);

// Technique 2: check if execution reached this point
printf("DEBUG: reached before loop\n");

// Technique 3: print loop variables every iteration
for (int i = 0; i < n; i++) {
  printf("DEBUG: i=%d, sum=%d\n", i, sum);
  sum += a[i];
}

// Technique 4: see which branch was taken
if (x > 0) {
  printf("DEBUG: x is positive\n");
} else {
  printf("DEBUG: x is 0 or negative\n");
}

Try it yourself

The code below is supposed to compute a sum, but a bug gives the wrong answer. Use printf debugging to find the cause.
Hint: Look at the DEBUG output. What value does i start at? Does a[5] even exist?

Common Bug Patterns

Knowing the bug patterns beginners often fall into will make your debugging far faster.
Off-by-one errors
Loop bounds off by one — starting at i=1 instead of i=0, or using i<=n where you meant i<n.
// NG: accesses a[5] (out of bounds)
for (int i = 0; i <= 5; i++) sum += a[i];
// OK:
for (int i = 0; i < 5; i++) sum += a[i];
Uninitialized variables
Declaring a variable without initializing it leaves it holding indeterminate (garbage) data.
int sum;       // ← initial value is garbage!
for (...) sum += a[i]; // garbage + a[i] = ?
// Correct: int sum = 0;
Confusing = with ==
if (x = 5) assigns 5 to x (and is always true). Use == for comparison.
if (x = 5)  // NG: assigns 5 to x (always true)
if (x == 5) // OK: checks whether x equals 5
Infinite loops
The loop variable is never updated, or the condition is always true.
int i = 0;
while (i < 10) {
  printf("%d\n", i);
  // forgot i++! -> i stays 0 forever
}
Missing & in scanf
It should be scanf("%d", &x), not scanf("%d", x). Without the address, scanf crashes.
scanf("%d", x);   // NG: crash!
scanf("%d", &x);  // OK

Bug Fix Challenge

The code below contains three bugs. Fix them so the output is exactly average = 5.00.
← Previous lesson
Lesson 16: Loops (for/while)
Next lesson →
Lesson 20: Arrays

Related lessons

Reference
Lesson 33: Compile Errors Dictionary
A catalog of C compile errors and how to fix them. A complete guide to reading gcc messages.
Reference
Lesson 34: Runtime Errors and Segfaults
Causes of segmentation faults in C and how to fix them. A complete guide to runtime errors.

Review Quiz

Check your understanding.

Q1. What is the purpose of printf debugging?

Decorate the screen
Inspect variable values during execution
Make the program faster

Printing variable values or execution markers with printf helps you pinpoint the cause of a bug. It's the most basic debugging technique.

Q2. What can a debugger (like gdb) do?

Automatically fix the code
Step through the code line by line and inspect variables
Speed up compilation

Debuggers let you set breakpoints, step through code, and watch variables — everything you need to analyze a program in detail.

Q3. Which is a good habit for avoiding bugs?

Write large amounts of code in one go
Compile and test frequently in small increments
Never write any comments

Writing small pieces of code and testing frequently lets you catch bugs quickly. Comments also help a lot.

Share this article
Share on X Share on Facebook