c

examples

examples.c🔧
/**
 * Introduction to the C Preprocessor - Examples
 * 
 * This file demonstrates the fundamental concepts and usage
 * of the C preprocessor including directives, macros, and more.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* ============================================================
 * Example 1: Object-like Macros (Constants)
 * ============================================================ */

/* Simple constant definitions */
#define PI 3.14159265358979
#define E  2.71828182845905
#define MAX_BUFFER_SIZE 1024
#define APP_NAME "Preprocessor Demo"
#define APP_VERSION "1.0.0"

/* Empty macro (used for conditional compilation) */
#define FEATURE_ENABLED

void example_constants(void) {
    printf("=== Example 1: Object-like Macros (Constants) ===\n\n");
    
    printf("Application: %s v%s\n", APP_NAME, APP_VERSION);
    printf("PI = %.15f\n", PI);
    printf("E = %.15f\n", E);
    printf("Buffer size: %d bytes\n", MAX_BUFFER_SIZE);
    
    /* Using constant in array declaration */
    char buffer[MAX_BUFFER_SIZE];
    printf("Buffer array created with %d elements\n\n", MAX_BUFFER_SIZE);
    
    (void)buffer; /* Suppress unused warning */
}

/* ============================================================
 * Example 2: Function-like Macros
 * ============================================================ */

/* Basic function macros */
#define SQUARE(x) ((x) * (x))
#define CUBE(x) ((x) * (x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define ABS(x) ((x) < 0 ? -(x) : (x))

/* Multi-parameter macros */
#define CLAMP(value, low, high) \
    (((value) < (low)) ? (low) : (((value) > (high)) ? (high) : (value)))

#define IN_RANGE(value, low, high) \
    ((value) >= (low) && (value) <= (high))

void example_function_macros(void) {
    printf("=== Example 2: Function-like Macros ===\n\n");
    
    int a = 5, b = 3;
    
    printf("a = %d, b = %d\n", a, b);
    printf("SQUARE(%d) = %d\n", a, SQUARE(a));
    printf("CUBE(%d) = %d\n", b, CUBE(b));
    printf("MAX(%d, %d) = %d\n", a, b, MAX(a, b));
    printf("MIN(%d, %d) = %d\n", a, b, MIN(a, b));
    printf("ABS(-7) = %d\n", ABS(-7));
    
    int value = 15;
    printf("\nCLAMP(%d, 0, 10) = %d\n", value, CLAMP(value, 0, 10));
    printf("IN_RANGE(%d, 0, 20) = %d\n", value, IN_RANGE(value, 0, 20));
    printf("IN_RANGE(%d, 0, 10) = %d\n", value, IN_RANGE(value, 0, 10));
    printf("\n");
}

/* ============================================================
 * Example 3: Why Parentheses Matter
 * ============================================================ */

/* BAD: Missing parentheses */
#define BAD_DOUBLE(x) x * 2
#define BAD_ADD(a, b) a + b

/* GOOD: Proper parentheses */
#define GOOD_DOUBLE(x) ((x) * 2)
#define GOOD_ADD(a, b) ((a) + (b))

void example_parentheses(void) {
    printf("=== Example 3: Why Parentheses Matter ===\n\n");
    
    printf("Testing with expression (3 + 4):\n");
    printf("BAD_DOUBLE(3 + 4) = %d (3 + 4 * 2 = 11, wrong!)\n", 
           BAD_DOUBLE(3 + 4));
    printf("GOOD_DOUBLE(3 + 4) = %d ((3 + 4) * 2 = 14, correct!)\n", 
           GOOD_DOUBLE(3 + 4));
    
    printf("\nTesting 10 / BAD_ADD(2, 3):\n");
    printf("10 / BAD_ADD(2, 3) = %d (10 / 2 + 3 = 8, wrong!)\n",
           10 / BAD_ADD(2, 3));
    printf("10 / GOOD_ADD(2, 3) = %d (10 / (2 + 3) = 2, correct!)\n",
           10 / GOOD_ADD(2, 3));
    printf("\n");
}

/* ============================================================
 * Example 4: Predefined Macros
 * ============================================================ */

void example_predefined_macros(void) {
    printf("=== Example 4: Predefined Macros ===\n\n");
    
    printf("__FILE__    = %s\n", __FILE__);
    printf("__LINE__    = %d\n", __LINE__);
    printf("__DATE__    = %s\n", __DATE__);
    printf("__TIME__    = %s\n", __TIME__);
    printf("__func__    = %s\n", __func__);
    
    #ifdef __STDC__
    printf("__STDC__    = %d (Standard conforming)\n", __STDC__);
    #endif
    
    #ifdef __STDC_VERSION__
    printf("__STDC_VERSION__ = %ldL\n", __STDC_VERSION__);
    
    #if __STDC_VERSION__ >= 202311L
        printf("              -> C23 or later\n");
    #elif __STDC_VERSION__ >= 201710L
        printf("              -> C17\n");
    #elif __STDC_VERSION__ >= 201112L
        printf("              -> C11\n");
    #elif __STDC_VERSION__ >= 199901L
        printf("              -> C99\n");
    #endif
    #endif
    
    printf("\n");
}

/* ============================================================
 * Example 5: Stringification Operator (#)
 * ============================================================ */

#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define PRINT_VAR(var) printf(#var " = %d\n", var)
#define PRINT_EXPR(expr) printf(#expr " = %d\n", (expr))

void example_stringification(void) {
    printf("=== Example 5: Stringification Operator (#) ===\n\n");
    
    /* Direct stringification */
    printf("STRINGIFY(hello) = %s\n", STRINGIFY(hello));
    printf("STRINGIFY(123) = %s\n", STRINGIFY(123));
    printf("STRINGIFY(a + b) = %s\n", STRINGIFY(a + b));
    
    /* Two-level stringification for macro values */
    #define VALUE 42
    printf("\nWith VALUE defined as 42:\n");
    printf("STRINGIFY(VALUE) = %s (macro name)\n", STRINGIFY(VALUE));
    printf("TOSTRING(VALUE) = %s (macro value)\n", TOSTRING(VALUE));
    
    /* Debugging with stringification */
    printf("\nDebugging variables:\n");
    int count = 10;
    int total = 250;
    PRINT_VAR(count);
    PRINT_VAR(total);
    
    printf("\nDebugging expressions:\n");
    PRINT_EXPR(count * 5);
    PRINT_EXPR(total / count);
    PRINT_EXPR(count > 5 ? 1 : 0);
    printf("\n");
}

/* ============================================================
 * Example 6: Token Pasting Operator (##)
 * ============================================================ */

#define CONCAT(a, b) a##b
#define MAKE_FUNC(name) void name##_function(void) { \
    printf("Called " #name "_function\n"); \
}

#define DECLARE_VAR(type, prefix, num) type prefix##num
#define ACCESS_MEMBER(obj, member) obj##.##member

/* Generate functions using token pasting */
MAKE_FUNC(alpha)
MAKE_FUNC(beta)
MAKE_FUNC(gamma)

void example_token_pasting(void) {
    printf("=== Example 6: Token Pasting Operator (##) ===\n\n");
    
    /* Creating variable names */
    int CONCAT(my, Variable) = 100;
    int CONCAT(counter, 1) = 10;
    int CONCAT(counter, 2) = 20;
    
    printf("myVariable = %d\n", myVariable);
    printf("counter1 = %d\n", counter1);
    printf("counter2 = %d\n", counter2);
    
    /* Declaring variables with generated names */
    DECLARE_VAR(int, value, A) = 5;
    DECLARE_VAR(int, value, B) = 10;
    printf("valueA = %d, valueB = %d\n", valueA, valueB);
    
    /* Calling generated functions */
    printf("\nCalling generated functions:\n");
    alpha_function();
    beta_function();
    gamma_function();
    printf("\n");
}

/* ============================================================
 * Example 7: Conditional Compilation with #ifdef/#ifndef
 * ============================================================ */

/* Define some feature flags */
#define DEBUG_MODE
#define FEATURE_LOGGING
/* #define FEATURE_PROFILING */  /* Commented out - disabled */

void example_ifdef(void) {
    printf("=== Example 7: Conditional Compilation (#ifdef/#ifndef) ===\n\n");
    
    #ifdef DEBUG_MODE
    printf("[DEBUG] Debug mode is ENABLED\n");
    #else
    printf("[INFO] Debug mode is DISABLED\n");
    #endif
    
    #ifndef DEBUG_MODE
    printf("This won't print because DEBUG_MODE is defined\n");
    #endif
    
    #ifdef FEATURE_LOGGING
    printf("[FEATURE] Logging is ENABLED\n");
    #endif
    
    #ifdef FEATURE_PROFILING
    printf("[FEATURE] Profiling is ENABLED\n");
    #else
    printf("[FEATURE] Profiling is DISABLED\n");
    #endif
    
    /* Nested conditionals */
    #ifdef DEBUG_MODE
        #ifdef FEATURE_LOGGING
        printf("[DEBUG+LOG] Both debug and logging enabled\n");
        #endif
    #endif
    
    printf("\n");
}

/* ============================================================
 * Example 8: Conditional Compilation with #if
 * ============================================================ */

#define VERSION_MAJOR 2
#define VERSION_MINOR 5
#define BUILD_NUMBER 1023

/* Combined version number */
#define VERSION ((VERSION_MAJOR * 10000) + (VERSION_MINOR * 100) + BUILD_NUMBER)

void example_if_directive(void) {
    printf("=== Example 8: Conditional Compilation (#if) ===\n\n");
    
    printf("Version: %d.%d.%d\n", VERSION_MAJOR, VERSION_MINOR, BUILD_NUMBER);
    
    #if VERSION_MAJOR >= 2
    printf("Version 2.x or higher features available\n");
    #endif
    
    #if VERSION_MAJOR == 2 && VERSION_MINOR >= 5
    printf("Version 2.5+ features available\n");
    #endif
    
    #if VERSION > 20000
    printf("Modern version (> 2.0.0)\n");
    #elif VERSION > 10000
    printf("Version 1.x\n");
    #else
    printf("Legacy version (< 1.0.0)\n");
    #endif
    
    /* Using defined() operator */
    #if defined(DEBUG_MODE) && defined(FEATURE_LOGGING)
    printf("Debug logging available\n");
    #endif
    
    #if !defined(NDEBUG)
    printf("Assertions are enabled (NDEBUG not defined)\n");
    #endif
    
    printf("\n");
}

/* ============================================================
 * Example 9: Platform Detection
 * ============================================================ */

void example_platform_detection(void) {
    printf("=== Example 9: Platform Detection ===\n\n");
    
    printf("Detected Platform: ");
    
    #if defined(_WIN32) || defined(_WIN64)
        printf("Windows");
        #ifdef _WIN64
            printf(" (64-bit)");
        #else
            printf(" (32-bit)");
        #endif
    #elif defined(__linux__)
        printf("Linux");
        #ifdef __ANDROID__
            printf(" (Android)");
        #endif
    #elif defined(__APPLE__) && defined(__MACH__)
        printf("macOS/iOS");
    #elif defined(__unix__)
        printf("Unix");
    #elif defined(__FreeBSD__)
        printf("FreeBSD");
    #else
        printf("Unknown");
    #endif
    
    printf("\n");
    
    printf("\nCompiler: ");
    #if defined(__clang__)
        printf("Clang %d.%d.%d\n", __clang_major__, __clang_minor__, 
               __clang_patchlevel__);
    #elif defined(__GNUC__)
        printf("GCC %d.%d.%d\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
    #elif defined(_MSC_VER)
        printf("MSVC %d\n", _MSC_VER);
    #else
        printf("Unknown compiler\n");
    #endif
    
    printf("\n");
}

/* ============================================================
 * Example 10: Multi-line Macros
 * ============================================================ */

/* Multi-line macro with do-while(0) pattern */
#define SAFE_FREE(ptr) do { \
    if ((ptr) != NULL) { \
        free(ptr); \
        (ptr) = NULL; \
    } \
} while(0)

/* Debug print macro */
#define DEBUG_PRINT(fmt, ...) do { \
    fprintf(stderr, "[DEBUG] %s:%d: ", __FILE__, __LINE__); \
    fprintf(stderr, fmt, ##__VA_ARGS__); \
    fprintf(stderr, "\n"); \
} while(0)

/* Assertion-like macro */
#define CHECK(condition) do { \
    if (!(condition)) { \
        fprintf(stderr, "Check failed: %s (file %s, line %d)\n", \
                #condition, __FILE__, __LINE__); \
    } \
} while(0)

void example_multiline_macros(void) {
    printf("=== Example 10: Multi-line Macros ===\n\n");
    
    /* SAFE_FREE example */
    int *ptr = malloc(sizeof(int));
    *ptr = 42;
    printf("Allocated ptr, value = %d\n", *ptr);
    
    SAFE_FREE(ptr);
    printf("After SAFE_FREE, ptr = %s\n", ptr == NULL ? "NULL" : "not null");
    
    /* Can safely call again */
    SAFE_FREE(ptr);  /* No crash because it checks for NULL */
    printf("Second SAFE_FREE call - no crash\n");
    
    /* DEBUG_PRINT example */
    printf("\nDEBUG_PRINT examples:\n");
    DEBUG_PRINT("Application starting");
    DEBUG_PRINT("Value is %d", 42);
    DEBUG_PRINT("Name: %s, Age: %d", "John", 25);
    
    /* CHECK example */
    printf("\nCHECK examples:\n");
    int x = 10;
    CHECK(x > 5);    /* Passes */
    CHECK(x == 10);  /* Passes */
    CHECK(x < 5);    /* Fails - prints message */
    
    printf("\n");
}

/* ============================================================
 * Example 11: Undef and Redefine
 * ============================================================ */

void example_undef(void) {
    printf("=== Example 11: #undef and Redefine ===\n\n");
    
    #define TEMP_VALUE 100
    printf("Initial TEMP_VALUE = %d\n", TEMP_VALUE);
    
    #undef TEMP_VALUE
    /* TEMP_VALUE is now undefined */
    
    #define TEMP_VALUE 200
    printf("After redefine, TEMP_VALUE = %d\n", TEMP_VALUE);
    
    /* Common use: Override library macros */
    #ifdef BUFFER_SIZE
    #undef BUFFER_SIZE
    #endif
    #define BUFFER_SIZE 4096
    printf("Custom BUFFER_SIZE = %d\n", BUFFER_SIZE);
    
    #undef TEMP_VALUE
    printf("\n");
}

/* ============================================================
 * Example 12: Error and Warning Directives
 * ============================================================ */

/* These would stop/warn during compilation if uncommented */
/* #error "This is a compile-time error message" */
/* #warning "This is a compile-time warning" */  /* Non-standard */

#define REQUIRED_VERSION 2

void example_error_directive(void) {
    printf("=== Example 12: #error and #warning Directives ===\n\n");
    
    /* Example of conditional error */
    #if REQUIRED_VERSION < 1
        #error "Version must be at least 1"
    #endif
    
    printf("Version check passed (REQUIRED_VERSION = %d)\n", REQUIRED_VERSION);
    
    /* Example usage patterns */
    printf("\nCommon #error patterns:\n");
    printf("  #error \"Missing configuration\"\n");
    printf("  #error \"Platform not supported\"\n");
    printf("  #error \"Feature X requires Y to be defined\"\n");
    
    printf("\n");
}

/* ============================================================
 * Example 13: Line Control (#line)
 * ============================================================ */

void example_line_directive(void) {
    printf("=== Example 13: #line Directive ===\n\n");
    
    printf("Before #line:\n");
    printf("  __LINE__ = %d\n", __LINE__);
    printf("  __FILE__ = %s\n", __FILE__);
    
    #line 1000 "virtual_file.c"
    printf("\nAfter #line 1000 \"virtual_file.c\":\n");
    printf("  __LINE__ = %d\n", __LINE__);
    printf("  __FILE__ = %s\n", __FILE__);
    
    /* Reset to approximate actual line */
    #line 250
    printf("\nAfter #line 250 (reset filename):\n");
    printf("  __LINE__ = %d\n", __LINE__);
    
    printf("\n(Note: #line is mainly used by code generators)\n\n");
}

/* ============================================================
 * Example 14: Pragma Directive
 * ============================================================ */

/* #pragma once - common header guard (shown in comments) */
/* #pragma pack(push, 1) - struct packing */

void example_pragma(void) {
    printf("=== Example 14: #pragma Directive ===\n\n");
    
    printf("Common #pragma directives:\n\n");
    
    printf("  #pragma once\n");
    printf("    - Include guard (non-standard but widely supported)\n\n");
    
    printf("  #pragma pack(push, 1)\n");
    printf("  #pragma pack(pop)\n");
    printf("    - Control struct member alignment\n\n");
    
    printf("  #pragma message(\"text\")\n");
    printf("    - Display message during compilation\n\n");
    
    printf("  #pragma GCC diagnostic ignored \"-Wunused\"\n");
    printf("    - Suppress specific warnings (GCC/Clang)\n\n");
    
    printf("  #pragma region / #pragma endregion\n");
    printf("    - Code folding regions (IDE support)\n\n");
    
    /* GCC-specific: Display message */
    #ifdef __GNUC__
    #pragma message("Compiling with GCC")
    #endif
}

/* ============================================================
 * Example 15: Complete Practical Example
 * ============================================================ */

/* Configuration macros */
#define PROJECT_NAME "ConfigDemo"
#define LOG_LEVEL_DEBUG 0
#define LOG_LEVEL_INFO 1
#define LOG_LEVEL_WARN 2
#define LOG_LEVEL_ERROR 3

#define CURRENT_LOG_LEVEL LOG_LEVEL_DEBUG

/* Logging macros with level filtering */
#define LOG_DEBUG(msg) do { \
    if (CURRENT_LOG_LEVEL <= LOG_LEVEL_DEBUG) \
        printf("[DEBUG] %s\n", msg); \
} while(0)

#define LOG_INFO(msg) do { \
    if (CURRENT_LOG_LEVEL <= LOG_LEVEL_INFO) \
        printf("[INFO] %s\n", msg); \
} while(0)

#define LOG_WARN(msg) do { \
    if (CURRENT_LOG_LEVEL <= LOG_LEVEL_WARN) \
        printf("[WARN] %s\n", msg); \
} while(0)

#define LOG_ERROR(msg) do { \
    if (CURRENT_LOG_LEVEL <= LOG_LEVEL_ERROR) \
        printf("[ERROR] %s\n", msg); \
} while(0)

/* Assert macro */
#ifndef NDEBUG
#define ASSERT(cond) do { \
    if (!(cond)) { \
        fprintf(stderr, "Assertion failed: %s\n", #cond); \
        fprintf(stderr, "  File: %s, Line: %d\n", __FILE__, __LINE__); \
        abort(); \
    } \
} while(0)
#else
#define ASSERT(cond) ((void)0)
#endif

/* Array size macro */
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

/* Unused parameter silencer */
#define UNUSED(x) ((void)(x))

void example_practical(void) {
    printf("=== Example 15: Practical Macros ===\n\n");
    
    printf("Project: %s\n\n", PROJECT_NAME);
    
    /* Logging examples */
    printf("Logging (level = DEBUG):\n");
    LOG_DEBUG("Entering function");
    LOG_INFO("Processing data");
    LOG_WARN("Resource running low");
    LOG_ERROR("Operation failed");
    
    /* Array size */
    int numbers[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    printf("\nArray has %zu elements\n", ARRAY_SIZE(numbers));
    
    /* Unused parameter */
    int unused_var = 42;
    UNUSED(unused_var);
    printf("Unused variable silenced without warning\n");
    
    /* Assert (won't fail here) */
    int value = 10;
    ASSERT(value > 0);
    ASSERT(value == 10);
    printf("Assertions passed\n");
    
    printf("\n");
}

/* ============================================================
 * Main Function
 * ============================================================ */

int main(void) {
    printf("\n");
    printf("╔══════════════════════════════════════════════════════════╗\n");
    printf("║     Introduction to C Preprocessor - Examples            ║\n");
    printf("╚══════════════════════════════════════════════════════════╝\n\n");
    
    example_constants();
    example_function_macros();
    example_parentheses();
    example_predefined_macros();
    example_stringification();
    example_token_pasting();
    example_ifdef();
    example_if_directive();
    example_platform_detection();
    example_multiline_macros();
    example_undef();
    example_error_directive();
    example_line_directive();
    example_pragma();
    example_practical();
    
    printf("╔══════════════════════════════════════════════════════════╗\n");
    printf("║                 All examples complete!                    ║\n");
    printf("╚══════════════════════════════════════════════════════════╝\n\n");
    
    return 0;
}
Examples - C Programming Tutorial | DeepML