C Debugging Techniques
In this page:
printf("DEBUG: variable = %d\n", variable);
printf("at %s:%d\n", __FILE__, __LINE__);
#ifdef DEBUG
printf("verbose debug output\n");
#endif
Printf Debugging
Inserting printf() calls at key points in your code to print the current values of variables is the simplest and most universal debugging technique in C, requiring no special tools, though it does mean remembering to remove or comment out the extra output before shipping the final program.
Example: Printf Debugging
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Program execution starts in main()
int main() {
// Declare x and set it to 5
int x = 5;
// Print formatted text to the screen
printf("DEBUG: x = %d\n", x);
x = x * 2;
// Print formatted text to the screen
printf("%d", x);
// Return 0 to signal that the program finished successfully
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Using Predefined Macros
The predefined macros __FILE__ and __LINE__ expand automatically to the current source file's name and the current line number, so embedding them in a debug print (e.g. printf("%s:%d value=%d\n", __FILE__, __LINE__, value);) tells you exactly where a given message came from without typing it manually.
Example: Using Predefined Macros
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Program execution starts in main()
int main() {
// Declare value and set it to 5
int value = 5;
// Print formatted text to the screen
printf("%s:%d value=%d\n", __FILE__, __LINE__, value);
// Return 0 to signal that the program finished successfully
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Conditional Debug Blocks
Wrapping debug output inside #ifdef DEBUG ... #endif blocks lets you compile the exact same source file with verbose diagnostic printing enabled for development builds and completely stripped out for release builds, just by defining or omitting the DEBUG macro at compile time.
Example: Conditional Debug Blocks
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Define the macro DEBUG (replaced by the preprocessor)
#define DEBUG
// Program execution starts in main()
int main() {
#ifdef DEBUG
// Print formatted text to the screen
printf("Debug output enabled\n");
#endif
// Print formatted text to the screen
printf("Normal output");
// Return 0 to signal that the program finished successfully
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Pointer Safety Checks
An uninitialized pointer holds whatever garbage address happened to be left in memory, so dereferencing it can crash unpredictably or, worse, silently corrupt unrelated memory.
Initializing every pointer to NULL immediately and checking for NULL before dereferencing turns a random crash into a predictable, debuggable one.
Example: Pointer Safety Checks
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Program execution starts in main()
int main() {
int *ptr = NULL;
// Check whether ptr == NULL
if (ptr == NULL) {
// Print formatted text to the screen
printf("Pointer not initialized safely -- avoided dereference");
}
// Return 0 to signal that the program finished successfully
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Dry Run Loop Traces
Off-by-one and boundary errors are among the most common loop bugs in C, so printing the loop index on every iteration while debugging quickly reveals whether a loop is running one time too many, one time too few, or accessing an index outside the array's valid range.
Example: Dry Run Loop Traces
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Program execution starts in main()
int main() {
// Loop: repeat while the condition holds
for (int i = 0; i < 3; i++) {
// Print formatted text to the screen
printf("Loop index: %d\n", i);
}
// Return 0 to signal that the program finished successfully
return 0;
}
Login to try C/C++/Java/PHP code in the editor
- Leaving debug
printfcalls in the finished program. - Ignoring compiler warnings, which often point to real bugs.
- Printing pointer or array values without checking that they are valid first.
Chapter Quiz — Complete all 20 topics to unlock
0/20 topics done
Complete these topics first:
- C typedef
- C Type Casting
- C Bit Fields
- C Variable Length Arrays
- C Command Line Arguments
- C Function Pointers
- C Callback Functions
- C Multidimensional Pointer
- C string.h Functions
- C stdlib.h Functions
- C math.h Functions
- C time.h Functions
- C ctype.h Functions
- C errno.h
- C assert.h
- C Error Handling
- C Debugging Techniques
- C Code Style & Best Practices
- C Common Mistakes
- C Interview Questions