← Back to C Course | Chapter 11: Preprocessor | Lesson 4 of 5

C Conditional Compilation

Conditional compilation lets you include or skip pieces of code depending on a setting, like a recipe with optional steps. It is used for different systems or debug modes.
Syntax
c
#ifdef MACRO_NAME
// compiled if MACRO_NAME is defined
#endif

#ifndef MACRO_NAME
#define MACRO_NAME
// compiled if MACRO_NAME is not defined
#endif

Using #ifdef

This is commonly used to include debug-only code, like #ifdef DEBUG ... #endif blocks that print extra diagnostic information, which are compiled out entirely (not just skipped at runtime) in release builds.

Example: Using #ifdef

c
// 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 info enabled");
	#endif
	// Return 0 to signal that the program finished successfully
	return 0;
}

Using #ifndef

This is the core mechanism behind include guards -- a header wraps its own contents in #ifndef HEADER_NAME so the second (and any subsequent) inclusion in the same file sees the guard macro already defined and skips the content entirely.

Example: Using #ifndef

c
#ifndef MY_HEADER_H
// Define the macro MY_HEADER_H (replaced by the preprocessor)
#define MY_HEADER_H
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Program execution starts in main()
int main() {
	// Print formatted text to the screen
	printf("Guarded content");
	// Return 0 to signal that the program finished successfully
	return 0;
}
#endif

Using #if, #elif, and #else

This mirrors the runtime if/else if/else structure but operates entirely at compile time, evaluating constant expressions (often involving defined() checks) to decide which code path actually gets compiled into the final binary.

Example: Using #if, #elif, and #else

c
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Define the macro VERSION (replaced by the preprocessor)
#define VERSION 2
// Program execution starts in main()
int main() {
	#if VERSION == 1
	// Print formatted text to the screen
	printf("Version 1");
	#elif VERSION == 2
	// Print formatted text to the screen
	printf("Version 2");
	#else
	printf("Unknown");
	#endif
	// Return 0 to signal that the program finished successfully
	return 0;
}

Using #undef in Logic Flows

This lets you toggle behavior mid-file for testing purposes -- undefining and redefining the same macro at different points changes what subsequent conditional blocks in the same file will include.

Example: Using #undef in Logic Flows

c
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Define the macro MODE (replaced by the preprocessor)
#define MODE 1
// Program execution starts in main()
int main() {
	#if MODE
	// Print formatted text to the screen
	printf("Mode active ");
	#endif
	#undef MODE
	// Define the macro MODE (replaced by the preprocessor)
	#define MODE 0
	#if MODE
	// Print formatted text to the screen
	printf("unreachable");
	#else
	printf("Mode toggled off");
	#endif
	// Return 0 to signal that the program finished successfully
	return 0;
}

Header Include Guards

The three-directive pattern (#ifndef, #define, #endif) wrapped around an entire header's contents is such a universal convention in C that most editors and IDEs can auto-generate it for you when creating a new header file.

Example: Header Include Guards

c
#ifndef POINT_H
// Define the macro POINT_H (replaced by the preprocessor)
#define POINT_H
// Include standard input/output (printf, scanf)
#include <stdio.h>
// Program execution starts in main()
int main() {
	// Print formatted text to the screen
	printf("Standard three-directive guard pattern");
	// Return 0 to signal that the program finished successfully
	return 0;
}
#endif
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Forgetting the closing #endif for an #ifdef or #if, which causes a compile error.
  2. Misspelling a macro name in #ifdef, so the block is silently skipped.
  3. Using #if on a macro that is not defined, where it is treated as 0 without a warning.
🔒

Chapter Quiz — Complete all 5 topics to unlock

0/5 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.