A structured lesson workspace with readable content, hands-on examples, and a clean path to completion.
#if evaluates a constant integer expression at preprocessing time. #elif provides additional branches. #else is the fallback. Unlike #ifdef, which only checks whether a macro exists, #if can compare values: #if VERSION >= 3, #if defined(__x86_64__) && defined(__linux__). This enables multi-way platform selection, version gating, and feature configuration based on numeric constants. The expressions must be evaluable at preprocessing time: no sizeof, no variables, no function calls.
#include <stdio.h>#define API_VERSION 3#define FEATURE_LOGGING 1#define FEATURE_METRICS 0int main(void) {#if API_VERSION >= 3printf("Using API v3+ protocol\n");#elif API_VERSION == 2printf("Using API v2 protocol\n");#elseprintf("Using legacy API v1 protocol\n");#endif#if FEATURE_LOGGINGprintf("Logging enabled\n");#endif#if FEATURE_METRICSprintf("Metrics enabled\n");#elseprintf("Metrics disabled\n");#endif#if defined(__x86_64__) || defined(__aarch64__)printf("64-bit architecture detected\n");#endifreturn 0;}
The preprocessor evaluated API_VERSION >= 3 as true and included the first branch. FEATURE_METRICS is 0, so the #else branch was taken. The architecture check used defined() inside a #if expression, combining existence checks with logical operators. The compiler only saw the included branches. The excluded code was stripped before compilation.
defined(MACRO) evaluates to 1 if MACRO is defined, 0 otherwise. It can be used inside #if expressions, unlike #ifdef which is a standalone directive. This lets you combine checks: #if defined(__linux__) && defined(__x86_64__). The parentheses around the macro name are optional but conventional. Use defined() when you need logical operators. Use #ifdef for simple existence checks.
#if/#elif/#else give you multi-way conditional compilation based on constant expressions. They are the configuration system of C: version selection, platform detection, feature toggles. All evaluated before the compiler runs. Next: #error, the directive that stops compilation with a custom message.
Finish the lesson once you have worked through the material. This awards ★ 30 XP.