C Academy · Lesson

Conditional Compilation

ifdef and macros.

Lesson 1 of 413 steps

Conditional Compilation is a free C Academy lesson on CoddyKit. This is lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C Academy learning path, and your progress syncs across the web and the CoddyKit app. The C Academy course includes 4 lessons in total.

The Preprocessor

Before the compiler ever sees your code, the preprocessor runs. It handles every line starting with #: includes, macros, and conditionals.

Conditional compilation lets you include or exclude blocks of code based on conditions evaluated at this stage, producing different builds from one source.

Defining Macros

#define creates a macro. With no value it is just a flag you can test later.

Object-like macros replace a name with text; flags simply mark that something is set.

#define MAX_USERS 100   /* value macro */
#define DEBUG          /* flag macro */

ifdef and ifndef

#ifdef NAME keeps the block only if NAME is defined. #ifndef keeps it only if NAME is not defined.

Here the debug print exists only in debug builds. Without DEBUG defined, the compiler never even sees that line.

#include <stdio.h>
#define DEBUG

int main(void) {
#ifdef DEBUG
    printf("debug: starting\n");
#endif
    printf("running\n");
    return 0;
}

if, elif, else

#if evaluates a constant integer expression. Combine with #elif and #else for multi-way selection.

This picks code based on a version number macro.

#include <stdio.h>
#define VERSION 2

int main(void) {
#if VERSION >= 2
    printf("new feature on\n");
#else
    printf("legacy mode\n");
#endif
    return 0;
}

The defined Operator

Inside #if you can test definition with defined(NAME), and combine tests with && and ||.

This is more flexible than #ifdef, which can only test one name.

#if defined(LINUX) && !defined(EMBEDDED)
    /* desktop Linux code */
#endif

Defining At Compile Time

You do not have to hardcode macros. The -D flag defines them on the command line.

This is how build systems switch features without editing source. -DDEBUG is the same as #define DEBUG at the top of every file.

gcc -DDEBUG -DVERSION=3 -o app app.c

Platform Detection

Compilers predefine macros describing the target. You use them to write portable code.

  • _WIN32 — Windows (32 or 64 bit)
  • __linux__ — Linux
  • __APPLE__ — macOS / iOS

Branch on these to call the right platform API.

#ifdef _WIN32
    #include <windows.h>
#else
    #include <unistd.h>
#endif

Header Include Guards

The classic use of conditionals is the include guard, which stops a header from being processed twice.

The first include defines the guard macro; subsequent includes skip the body because the macro is already defined.

#ifndef UTILS_H
#define UTILS_H

int add(int a, int b);

#endif /* UTILS_H */

Commenting Out Code

#if 0 ... #endif reliably disables a block, even one that already contains comments.

Unlike /* */, it nests safely, so it is the standard way to temporarily exclude code during debugging.

#if 0
    legacy_function();   /* disabled for now */
    /* with internal comments too */
#endif

Inspecting Preprocessor Output

To see exactly what the compiler will compile, run only the preprocessor with -E.

This expands all includes, macros, and conditionals, which is invaluable when a macro misbehaves.

gcc -E app.c | less

Feature Toggles In Practice

A common pattern is a single config header that turns features on or off for the whole project.

Flip one #define and every guarded block across all files responds. This keeps optional features cleanly separated from the core code.

#include <stdio.h>
#define FEATURE_LOGGING 1

int main(void) {
#if FEATURE_LOGGING
    printf("logging enabled\n");
#endif
    printf("app ready\n");
    return 0;
}

Quick Check

Predict the behavior of a command-line define.

Recap

You now control conditional compilation:

  • #ifdef/#ifndef test whether a macro is defined
  • #if/#elif/#else evaluate constant expressions, with defined()
  • -DNAME defines macros from the command line for feature switching
  • Predefined platform macros enable portable code; include guards prevent double inclusion

Next: organizing code across multiple files.

Free to start

Learn C with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
39
Lessons
144

Frequently Asked Questions

Is the “Conditional Compilation” lesson free?

Yes — the full text of “Conditional Compilation” is free to read here on the web. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C Academy course, upgrade to CoddyKit PRO. The C Academy course includes 4 lessons in total.

What will I learn in “Conditional Compilation”?

ifdef and macros. You practise C Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C Academy?

No prior experience is required. C Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 1 of 4.

How long does the “Conditional Compilation” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C Academy lesson?

Yes. Every C Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Conditional Compilation
  2. Multi-File Projects
  3. Makefiles
  4. Static and Shared Libraries
← Back to C Academy