c

examples

examples.c🔧
/**
 * =============================================================================
 * Macros and Definitions in C - Examples
 * =============================================================================
 * 
 * This file demonstrates various types of macros and their applications in C
 * programming. Each example is self-contained and well-documented.
 * 
 * Compile: gcc -Wall -Wextra -std=c99 -o examples examples.c
 * Run: ./examples
 * 
 * Topics Covered:
 * 1. Object-like Macros
 * 2. Function-like Macros
 * 3. Stringification Operator
 * 4. Token Pasting Operator
 * 5. Variadic Macros
 * 6. Advanced Macro Techniques
 * =============================================================================
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stddef.h>  // For offsetof

// =============================================================================
// Example 1: Basic Object-like Macros
// =============================================================================

#define PI 3.14159265359
#define E  2.71828182845
#define MAX_BUFFER_SIZE 1024
#define PROGRAM_NAME "Macro Examples"
#define VERSION_MAJOR 1
#define VERSION_MINOR 0
#define VERSION_PATCH 0

void example_object_macros(void) {
    printf("\n=== Example 1: Object-like Macros ===\n");
    
    printf("Program: %s\n", PROGRAM_NAME);
    printf("Version: %d.%d.%d\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
    printf("\n");
    
    // Using numeric constants
    double radius = 5.0;
    double area = PI * radius * radius;
    double circumference = 2 * PI * radius;
    
    printf("Circle with radius %.2f:\n", radius);
    printf("  Area: %.4f\n", area);
    printf("  Circumference: %.4f\n", circumference);
    printf("\n");
    
    // Buffer allocation using macro
    char buffer[MAX_BUFFER_SIZE];
    snprintf(buffer, sizeof(buffer), "Buffer size is %d bytes", MAX_BUFFER_SIZE);
    printf("%s\n", buffer);
}

// =============================================================================
// Example 2: Multi-line and Expression Macros
// =============================================================================

#define DOUBLE_BUFFER_SIZE (MAX_BUFFER_SIZE * 2)
#define HALF_BUFFER_SIZE   (MAX_BUFFER_SIZE / 2)

#define HEADER_TEXT "====================================\n" \
                    "     PROGRAM OUTPUT REPORT          \n" \
                    "====================================\n"

#define FOOTER_TEXT "====================================\n" \
                    "           END OF REPORT            \n" \
                    "===================================="

void example_multiline_macros(void) {
    printf("\n=== Example 2: Multi-line and Expression Macros ===\n");
    
    printf(HEADER_TEXT);
    printf("Single buffer size: %d\n", MAX_BUFFER_SIZE);
    printf("Double buffer size: %d\n", DOUBLE_BUFFER_SIZE);
    printf("Half buffer size: %d\n", HALF_BUFFER_SIZE);
    printf(FOOTER_TEXT);
    printf("\n");
}

// =============================================================================
// Example 3: Basic Function-like 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))
#define CLAMP(x, lo, hi) (MIN(MAX((x), (lo)), (hi)))

void example_function_macros(void) {
    printf("\n=== Example 3: Basic Function-like Macros ===\n");
    
    int a = 5, b = 8;
    printf("a = %d, b = %d\n", a, b);
    printf("SQUARE(%d) = %d\n", a, SQUARE(a));
    printf("CUBE(%d) = %d\n", a, CUBE(a));
    printf("MAX(%d, %d) = %d\n", a, b, MAX(a, b));
    printf("MIN(%d, %d) = %d\n", a, b, MIN(a, b));
    printf("\n");
    
    int x = -15;
    printf("x = %d\n", x);
    printf("ABS(%d) = %d\n", x, ABS(x));
    printf("\n");
    
    int value = 150;
    int low = 0, high = 100;
    printf("CLAMP(%d, %d, %d) = %d\n", value, low, high, CLAMP(value, low, high));
    
    value = -50;
    printf("CLAMP(%d, %d, %d) = %d\n", value, low, high, CLAMP(value, low, high));
    
    value = 50;
    printf("CLAMP(%d, %d, %d) = %d\n", value, low, high, CLAMP(value, low, high));
}

// =============================================================================
// Example 4: Importance of Parentheses
// =============================================================================

// Wrong way - missing parentheses
#define BAD_DOUBLE(x) x * 2
#define BAD_SQUARE(x) x * x

// Right way - with parentheses
#define GOOD_DOUBLE(x) ((x) * 2)
#define GOOD_SQUARE(x) ((x) * (x))

void example_parentheses_importance(void) {
    printf("\n=== Example 4: Importance of Parentheses ===\n");
    
    int result;
    
    // Demonstrate the problem with missing parentheses
    printf("Testing with expression (3 + 4):\n");
    
    result = BAD_DOUBLE(3 + 4);
    printf("  BAD_DOUBLE(3 + 4)  = %d  (3 + 4 * 2 = 11, wrong!)\n", result);
    
    result = GOOD_DOUBLE(3 + 4);
    printf("  GOOD_DOUBLE(3 + 4) = %d  (((3 + 4)) * 2 = 14, correct!)\n", result);
    printf("\n");
    
    printf("Testing with expression (2 + 3):\n");
    
    result = BAD_SQUARE(2 + 3);
    printf("  BAD_SQUARE(2 + 3)  = %d  (2 + 3 * 2 + 3 = 11, wrong!)\n", result);
    
    result = GOOD_SQUARE(2 + 3);
    printf("  GOOD_SQUARE(2 + 3) = %d  (((2 + 3)) * ((2 + 3)) = 25, correct!)\n", result);
}

// =============================================================================
// Example 5: Multi-statement Macros with do-while
// =============================================================================

// Wrong way - multiple statements without do-while
#define BAD_SWAP(a, b) { int temp = a; a = b; b = temp; }

// Right way - using do-while(0)
#define SWAP_INT(a, b) do { \
    int temp = (a);         \
    (a) = (b);              \
    (b) = temp;             \
} while(0)

#define PRINT_ARRAY(arr, size) do { \
    printf("[");                    \
    for (int _i = 0; _i < (size); _i++) { \
        if (_i > 0) printf(", ");   \
        printf("%d", (arr)[_i]);    \
    }                               \
    printf("]\n");                  \
} while(0)

void example_multistatement_macros(void) {
    printf("\n=== Example 5: Multi-statement Macros ===\n");
    
    int x = 10, y = 20;
    printf("Before swap: x = %d, y = %d\n", x, y);
    SWAP_INT(x, y);
    printf("After swap:  x = %d, y = %d\n", x, y);
    printf("\n");
    
    int arr[] = {1, 2, 3, 4, 5};
    int size = sizeof(arr) / sizeof(arr[0]);
    printf("Array: ");
    PRINT_ARRAY(arr, size);
}

// =============================================================================
// Example 6: 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))

#define VERSION 100
#define BUILD_NUMBER 2024

void example_stringification(void) {
    printf("\n=== Example 6: Stringification Operator (#) ===\n");
    
    // Basic stringification
    printf("STRINGIFY(Hello World) = %s\n", STRINGIFY(Hello World));
    printf("STRINGIFY(3.14159) = %s\n", STRINGIFY(3.14159));
    printf("\n");
    
    // Two-level stringification
    printf("STRINGIFY(VERSION) = %s (just the name)\n", STRINGIFY(VERSION));
    printf("TOSTRING(VERSION) = %s (the value)\n", TOSTRING(VERSION));
    printf("TOSTRING(BUILD_NUMBER) = %s\n", TOSTRING(BUILD_NUMBER));
    printf("\n");
    
    // Practical use: printing variable names with values
    int count = 42;
    int total = 100;
    PRINT_VAR(count);
    PRINT_VAR(total);
    printf("\n");
    
    // Printing expressions
    int a = 5, b = 7;
    PRINT_EXPR(a + b);
    PRINT_EXPR(a * b);
    PRINT_EXPR(a + b * 2);
}

// =============================================================================
// Example 7: Token Pasting Operator (##)
// =============================================================================

#define CONCAT(a, b) a ## b
#define MAKE_VAR(name, num) name ## num

// Create getter and setter functions
#define DECLARE_ACCESSORS(type, name) \
    static type _##name; \
    static type get_##name(void) { return _##name; } \
    static void set_##name(type value) { _##name = value; }

// Generate print functions for different types
#define DEFINE_PRINT(type, fmt) \
    void print_##type(type value) { \
        printf(#type ": " fmt "\n", value); \
    }

DECLARE_ACCESSORS(int, score)
DECLARE_ACCESSORS(float, rate)

DEFINE_PRINT(int, "%d")
DEFINE_PRINT(float, "%f")
DEFINE_PRINT(double, "%lf")

void example_token_pasting(void) {
    printf("\n=== Example 7: Token Pasting Operator (##) ===\n");
    
    // Basic concatenation
    int CONCAT(my, Var) = 100;
    int MAKE_VAR(count, 1) = 10;
    int MAKE_VAR(count, 2) = 20;
    
    printf("myVar = %d\n", myVar);
    printf("count1 = %d\n", count1);
    printf("count2 = %d\n", count2);
    printf("\n");
    
    // Using generated accessor functions
    set_score(95);
    set_rate(3.14f);
    
    printf("Score: %d\n", get_score());
    printf("Rate: %.2f\n", get_rate());
    printf("\n");
    
    // Using generated print functions
    print_int(42);
    print_float(3.14159f);
    print_double(2.71828);
}

// =============================================================================
// Example 8: Variadic Macros
// =============================================================================

#define SIMPLE_PRINT(...) printf(__VA_ARGS__)

#define LOG_INFO(fmt, ...)  printf("[INFO]  " fmt "\n", ##__VA_ARGS__)
#define LOG_WARN(fmt, ...)  printf("[WARN]  " fmt "\n", ##__VA_ARGS__)
#define LOG_ERROR(fmt, ...) printf("[ERROR] " fmt "\n", ##__VA_ARGS__)

#define DEBUG_LOG(fmt, ...) \
    printf("[DEBUG %s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)

void example_variadic_macros(void) {
    printf("\n=== Example 8: Variadic Macros ===\n");
    
    // Simple variadic macro
    SIMPLE_PRINT("Hello, World!\n");
    SIMPLE_PRINT("Value: %d\n", 42);
    SIMPLE_PRINT("Sum of %d and %d is %d\n", 10, 20, 30);
    printf("\n");
    
    // Logging macros
    LOG_INFO("Application started");
    LOG_INFO("Processing file: %s", "data.txt");
    LOG_WARN("Low memory: %d%% available", 15);
    LOG_ERROR("Failed to open file: %s (error %d)", "missing.txt", 404);
    printf("\n");
    
    // Debug logging with file and line
    DEBUG_LOG("Starting processing");
    DEBUG_LOG("Processing item %d", 42);
}

// =============================================================================
// Example 9: Array and Memory Macros
// =============================================================================

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

#define SAFE_FREE(ptr) do { \
    if ((ptr) != NULL) {    \
        free(ptr);          \
        (ptr) = NULL;       \
    }                       \
} while(0)

#define SAFE_ALLOC(ptr, type, count) do { \
    (ptr) = (type *)malloc(sizeof(type) * (count)); \
    if ((ptr) == NULL) { \
        fprintf(stderr, "Memory allocation failed at %s:%d\n", __FILE__, __LINE__); \
    } \
} while(0)

#define ZERO_ARRAY(arr) memset((arr), 0, sizeof(arr))

#define FOREACH_INDEX(i, arr) \
    for (size_t i = 0; i < ARRAY_SIZE(arr); i++)

void example_array_memory_macros(void) {
    printf("\n=== Example 9: Array and Memory Macros ===\n");
    
    // ARRAY_SIZE usage
    int numbers[] = {10, 20, 30, 40, 50};
    char name[] = "Hello";
    double values[] = {1.1, 2.2, 3.3};
    
    printf("Size of numbers array: %zu\n", ARRAY_SIZE(numbers));
    printf("Size of name array: %zu (including null)\n", ARRAY_SIZE(name));
    printf("Size of values array: %zu\n", ARRAY_SIZE(values));
    printf("\n");
    
    // FOREACH_INDEX usage
    printf("Numbers: ");
    FOREACH_INDEX(i, numbers) {
        printf("%d ", numbers[i]);
    }
    printf("\n\n");
    
    // SAFE_ALLOC and SAFE_FREE
    int *dynamic_arr = NULL;
    SAFE_ALLOC(dynamic_arr, int, 5);
    
    if (dynamic_arr) {
        for (int i = 0; i < 5; i++) {
            dynamic_arr[i] = (i + 1) * 10;
        }
        
        printf("Dynamic array: ");
        for (int i = 0; i < 5; i++) {
            printf("%d ", dynamic_arr[i]);
        }
        printf("\n");
        
        SAFE_FREE(dynamic_arr);
        printf("After SAFE_FREE, pointer is: %p\n", (void *)dynamic_arr);
    }
    printf("\n");
    
    // ZERO_ARRAY usage
    int buffer[5] = {1, 2, 3, 4, 5};
    printf("Before ZERO_ARRAY: ");
    for (int i = 0; i < 5; i++) printf("%d ", buffer[i]);
    printf("\n");
    
    ZERO_ARRAY(buffer);
    printf("After ZERO_ARRAY:  ");
    for (int i = 0; i < 5; i++) printf("%d ", buffer[i]);
    printf("\n");
}

// =============================================================================
// Example 10: Bit Manipulation Macros
// =============================================================================

#define SET_BIT(n, bit)     ((n) |  (1 << (bit)))
#define CLEAR_BIT(n, bit)   ((n) & ~(1 << (bit)))
#define TOGGLE_BIT(n, bit)  ((n) ^  (1 << (bit)))
#define CHECK_BIT(n, bit)   (((n) >> (bit)) & 1)
#define GET_BIT(n, bit)     CHECK_BIT(n, bit)

#define SET_BITS(n, mask)   ((n) | (mask))
#define CLEAR_BITS(n, mask) ((n) & ~(mask))
#define TOGGLE_BITS(n, mask) ((n) ^ (mask))

#define PRINT_BINARY(n) do { \
    printf(#n " = 0b"); \
    for (int _i = 7; _i >= 0; _i--) { \
        printf("%d", ((n) >> _i) & 1); \
    } \
    printf(" (%d)\n", n); \
} while(0)

void example_bit_macros(void) {
    printf("\n=== Example 10: Bit Manipulation Macros ===\n");
    
    unsigned char value = 0b00001010;  // 10 in decimal
    PRINT_BINARY(value);
    printf("\n");
    
    // SET_BIT
    unsigned char set = SET_BIT(value, 0);  // Set bit 0
    printf("After SET_BIT(value, 0):\n");
    PRINT_BINARY(set);
    
    // CLEAR_BIT
    unsigned char clear = CLEAR_BIT(value, 1);  // Clear bit 1
    printf("\nAfter CLEAR_BIT(value, 1):\n");
    PRINT_BINARY(clear);
    
    // TOGGLE_BIT
    unsigned char toggle = TOGGLE_BIT(value, 3);  // Toggle bit 3
    printf("\nAfter TOGGLE_BIT(value, 3):\n");
    PRINT_BINARY(toggle);
    
    // CHECK_BIT
    printf("\nChecking bits in value (0b00001010):\n");
    for (int i = 7; i >= 0; i--) {
        printf("  Bit %d: %d\n", i, CHECK_BIT(value, i));
    }
}

// =============================================================================
// Example 11: Predefined Macros
// =============================================================================

void example_predefined_macros(void) {
    printf("\n=== Example 11: Predefined Macros ===\n");
    
    // Standard predefined macros
    printf("File: %s\n", __FILE__);
    printf("Line: %d\n", __LINE__);
    printf("Date: %s\n", __DATE__);
    printf("Time: %s\n", __TIME__);
    printf("Function: %s\n", __func__);  // C99
    printf("\n");
    
    // Standard version
#ifdef __STDC__
    printf("ANSI C compliant: Yes\n");
#else
    printf("ANSI C compliant: No\n");
#endif

#ifdef __STDC_VERSION__
    printf("C Standard Version: %ld\n", __STDC_VERSION__);
    #if __STDC_VERSION__ >= 201112L
        printf("  (C11 or later)\n");
    #elif __STDC_VERSION__ >= 199901L
        printf("  (C99)\n");
    #endif
#endif

    printf("\n");
    
    // Compiler-specific macros
#ifdef __GNUC__
    printf("GCC Version: %d.%d.%d\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
#endif

#ifdef __clang__
    printf("Clang compiler detected\n");
#endif
}

// =============================================================================
// Example 12: Debug and Assert Macros
// =============================================================================

// Enable debug mode for this example
#define DEBUG_MODE 1

#if DEBUG_MODE
    #define DBG_PRINT(fmt, ...) \
        fprintf(stderr, "[DEBUG %s:%d] " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)
    
    #define DBG_ASSERT(condition) do { \
        if (!(condition)) { \
            fprintf(stderr, "ASSERTION FAILED: %s\n", #condition); \
            fprintf(stderr, "  File: %s\n", __FILE__); \
            fprintf(stderr, "  Line: %d\n", __LINE__); \
            fprintf(stderr, "  Function: %s\n", __func__); \
        } \
    } while(0)
    
    #define DBG_TRACE() \
        fprintf(stderr, "[TRACE] Entering %s()\n", __func__)
#else
    #define DBG_PRINT(fmt, ...) ((void)0)
    #define DBG_ASSERT(condition) ((void)0)
    #define DBG_TRACE() ((void)0)
#endif

// Custom assert that doesn't abort
#define SOFT_ASSERT(condition, msg) do { \
    if (!(condition)) { \
        fprintf(stderr, "Warning: %s (%s)\n", msg, #condition); \
    } \
} while(0)

void helper_function(int value) {
    DBG_TRACE();
    DBG_PRINT("Processing value: %d", value);
    DBG_ASSERT(value > 0);
}

void example_debug_macros(void) {
    printf("\n=== Example 12: Debug and Assert Macros ===\n");
    
    DBG_TRACE();
    
    int x = 10;
    DBG_PRINT("Starting with x = %d", x);
    
    helper_function(x);
    helper_function(-5);  // Will trigger assertion
    
    printf("\n");
    
    // Soft assertions
    int score = 150;
    SOFT_ASSERT(score >= 0 && score <= 100, "Score out of valid range");
    
    char *name = NULL;
    SOFT_ASSERT(name != NULL, "Name pointer is null");
}

// =============================================================================
// Example 13: Type-Generic Macros (C11 _Generic)
// =============================================================================

#if __STDC_VERSION__ >= 201112L

#define TYPE_NAME(x) _Generic((x), \
    int: "int", \
    float: "float", \
    double: "double", \
    char *: "char pointer", \
    int *: "int pointer", \
    default: "unknown")

#define PRINT_VALUE(x) _Generic((x), \
    int: printf("int: %d\n", x), \
    float: printf("float: %f\n", x), \
    double: printf("double: %lf\n", x), \
    char *: printf("string: %s\n", x), \
    default: printf("unknown type\n"))

void example_generic_macros(void) {
    printf("\n=== Example 13: Type-Generic Macros (C11) ===\n");
    
    int i = 42;
    float f = 3.14f;
    double d = 2.71828;
    char *s = "Hello";
    
    printf("Type of i: %s\n", TYPE_NAME(i));
    printf("Type of f: %s\n", TYPE_NAME(f));
    printf("Type of d: %s\n", TYPE_NAME(d));
    printf("Type of s: %s\n", TYPE_NAME(s));
    printf("\n");
    
    PRINT_VALUE(i);
    PRINT_VALUE(f);
    PRINT_VALUE(d);
    PRINT_VALUE(s);
}

#else

void example_generic_macros(void) {
    printf("\n=== Example 13: Type-Generic Macros ===\n");
    printf("(C11 _Generic not available in this compiler)\n");
}

#endif

// =============================================================================
// Example 14: X-Macro Technique
// =============================================================================

// Define colors using X-macro
#define COLOR_LIST \
    X(COLOR_RED,    "Red",    0xFF0000) \
    X(COLOR_GREEN,  "Green",  0x00FF00) \
    X(COLOR_BLUE,   "Blue",   0x0000FF) \
    X(COLOR_YELLOW, "Yellow", 0xFFFF00) \
    X(COLOR_CYAN,   "Cyan",   0x00FFFF) \
    X(COLOR_WHITE,  "White",  0xFFFFFF) \
    X(COLOR_BLACK,  "Black",  0x000000)

// Generate enum
#define X(name, str, val) name,
typedef enum { COLOR_LIST COLOR_COUNT } Color;
#undef X

// Generate string array
#define X(name, str, val) [name] = str,
static const char *color_names[] = { COLOR_LIST };
#undef X

// Generate hex value array
#define X(name, str, val) [name] = val,
static const int color_values[] = { COLOR_LIST };
#undef X

// Function to get color info
void print_color_info(Color c) {
    if (c < COLOR_COUNT) {
        printf("Color: %-8s  Hex: 0x%06X\n", color_names[c], color_values[c]);
    }
}

void example_xmacro(void) {
    printf("\n=== Example 14: X-Macro Technique ===\n");
    
    printf("Total colors defined: %d\n\n", COLOR_COUNT);
    
    printf("All colors:\n");
    for (Color c = 0; c < COLOR_COUNT; c++) {
        print_color_info(c);
    }
    printf("\n");
    
    // Using the enum values
    Color myColor = COLOR_BLUE;
    printf("My color is %s (0x%06X)\n", color_names[myColor], color_values[myColor]);
}

// =============================================================================
// Example 15: Container and Struct Macros
// =============================================================================

// Get pointer to struct containing this member
#define container_of(ptr, type, member) \
    ((type *)((char *)(ptr) - offsetof(type, member)))

// Define a simple linked list node
typedef struct ListNode {
    int data;
    struct ListNode *next;
} ListNode;

// Wrapper structure containing a ListNode
typedef struct {
    char name[32];
    int id;
    ListNode node;  // Embedded node
} Person;

// Initialize a structure with default values
#define INIT_PERSON(p, n, i) do { \
    strncpy((p)->name, (n), sizeof((p)->name) - 1); \
    (p)->name[sizeof((p)->name) - 1] = '\0'; \
    (p)->id = (i); \
    (p)->node.data = 0; \
    (p)->node.next = NULL; \
} while(0)

void example_container_macros(void) {
    printf("\n=== Example 15: Container and Struct Macros ===\n");
    
    Person alice;
    INIT_PERSON(&alice, "Alice", 1001);
    
    printf("Person: %s (ID: %d)\n", alice.name, alice.id);
    printf("Address of alice: %p\n", (void *)&alice);
    printf("Address of alice.node: %p\n", (void *)&alice.node);
    
    // Recover Person pointer from node pointer
    ListNode *node_ptr = &alice.node;
    Person *recovered = container_of(node_ptr, Person, node);
    
    printf("Recovered from node: %s (ID: %d)\n", recovered->name, recovered->id);
    printf("container_of result: %p\n", (void *)recovered);
    printf("Same as original: %s\n", (recovered == &alice) ? "Yes" : "No");
}

// =============================================================================
// Example 16: State Machine Macros
// =============================================================================

// State machine state definitions
#define STATE_LIST \
    STATE(IDLE,     "Idle") \
    STATE(RUNNING,  "Running") \
    STATE(PAUSED,   "Paused") \
    STATE(STOPPED,  "Stopped")

// Generate state enum
#define STATE(name, str) STATE_##name,
typedef enum { STATE_LIST STATE_COUNT } MachineState;
#undef STATE

// Generate state name strings
#define STATE(name, str) [STATE_##name] = str,
static const char *state_names[] = { STATE_LIST };
#undef STATE

// State transition macro
#define TRANSITION(machine, new_state) do { \
    printf("Transition: %s -> %s\n", \
           state_names[(machine)], state_names[(new_state)]); \
    (machine) = (new_state); \
} while(0)

void example_state_machine(void) {
    printf("\n=== Example 16: State Machine Macros ===\n");
    
    MachineState machine = STATE_IDLE;
    printf("Initial state: %s\n\n", state_names[machine]);
    
    TRANSITION(machine, STATE_RUNNING);
    TRANSITION(machine, STATE_PAUSED);
    TRANSITION(machine, STATE_RUNNING);
    TRANSITION(machine, STATE_STOPPED);
    
    printf("\nFinal state: %s\n", state_names[machine]);
}

// =============================================================================
// Example 17: Build Configuration Macros
// =============================================================================

// Simulated build configuration
#define CONFIG_DEBUG 1
#define CONFIG_LOG_LEVEL 2  // 0=none, 1=error, 2=warn, 3=info, 4=debug
#define CONFIG_FEATURE_A 1
#define CONFIG_FEATURE_B 0
#define CONFIG_MAX_CONNECTIONS 100

// Feature toggle macros
#if CONFIG_FEATURE_A
    #define feature_a_enabled() (1)
    #define FEATURE_A_CODE(code) code
#else
    #define feature_a_enabled() (0)
    #define FEATURE_A_CODE(code)
#endif

#if CONFIG_FEATURE_B
    #define feature_b_enabled() (1)
    #define FEATURE_B_CODE(code) code
#else
    #define feature_b_enabled() (0)
    #define FEATURE_B_CODE(code)
#endif

// Log level macros
#if CONFIG_LOG_LEVEL >= 1
    #define LOG_ERR(msg) printf("[ERR]  %s\n", msg)
#else
    #define LOG_ERR(msg)
#endif

#if CONFIG_LOG_LEVEL >= 2
    #define LOG_WRN(msg) printf("[WARN] %s\n", msg)
#else
    #define LOG_WRN(msg)
#endif

#if CONFIG_LOG_LEVEL >= 3
    #define LOG_INF(msg) printf("[INFO] %s\n", msg)
#else
    #define LOG_INF(msg)
#endif

#if CONFIG_LOG_LEVEL >= 4
    #define LOG_DBG(msg) printf("[DBG]  %s\n", msg)
#else
    #define LOG_DBG(msg)
#endif

void example_build_config(void) {
    printf("\n=== Example 17: Build Configuration Macros ===\n");
    
    printf("Configuration:\n");
    printf("  Debug mode: %s\n", CONFIG_DEBUG ? "enabled" : "disabled");
    printf("  Log level: %d\n", CONFIG_LOG_LEVEL);
    printf("  Feature A: %s\n", feature_a_enabled() ? "enabled" : "disabled");
    printf("  Feature B: %s\n", feature_b_enabled() ? "enabled" : "disabled");
    printf("  Max connections: %d\n", CONFIG_MAX_CONNECTIONS);
    printf("\n");
    
    // Log level demonstration
    LOG_ERR("This is an error");
    LOG_WRN("This is a warning");
    LOG_INF("This is info");       // Won't show (level 2 < 3)
    LOG_DBG("This is debug");      // Won't show (level 2 < 4)
    printf("\n");
    
    // Feature toggle demonstration
    FEATURE_A_CODE(printf("Feature A code is included\n");)
    FEATURE_B_CODE(printf("Feature B code is included\n");)  // Won't compile in
    
    if (feature_a_enabled()) {
        printf("Running Feature A logic...\n");
    }
    
    if (feature_b_enabled()) {
        printf("Running Feature B logic...\n");  // Won't execute
    }
}

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

int main(void) {
    printf("============================================================\n");
    printf("         MACROS AND DEFINITIONS IN C - EXAMPLES             \n");
    printf("============================================================\n");
    
    example_object_macros();
    example_multiline_macros();
    example_function_macros();
    example_parentheses_importance();
    example_multistatement_macros();
    example_stringification();
    example_token_pasting();
    example_variadic_macros();
    example_array_memory_macros();
    example_bit_macros();
    example_predefined_macros();
    example_debug_macros();
    example_generic_macros();
    example_xmacro();
    example_container_macros();
    example_state_machine();
    example_build_config();
    
    printf("\n============================================================\n");
    printf("                  ALL EXAMPLES COMPLETED                     \n");
    printf("============================================================\n");
    
    return 0;
}
Examples - C Programming Tutorial | DeepML