c

examples

examples.c🔧
/**
 * =============================================================================
 * Conditional Compilation in C - Examples
 * =============================================================================
 * 
 * This file demonstrates various conditional compilation techniques in C.
 * Different sections can be enabled/disabled by defining macros before
 * compilation or using compiler flags like -DDEBUG.
 * 
 * Compile examples:
 *   gcc -Wall -Wextra -std=c99 -o examples examples.c
 *   gcc -DDEBUG -o examples_debug examples.c
 *   gcc -DPLATFORM_LINUX -o examples_linux examples.c
 * 
 * Topics Covered:
 * 1. Basic #ifdef and #ifndef
 * 2. #if, #elif, #else directives
 * 3. defined() operator
 * 4. Platform-specific code
 * 5. Debug vs Release builds
 * 6. Feature toggles
 * =============================================================================
 */

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

// =============================================================================
// Configuration Section - Modify these to see different behaviors
// =============================================================================

// Uncomment to enable debug mode
// #define DEBUG

// Uncomment to enable verbose output
// #define VERBOSE

// Set version (1, 2, or 3)
#define VERSION 2

// Set feature flags
#define FEATURE_LOGGING 1
#define FEATURE_CACHING 1
#define FEATURE_STATISTICS 0

// Set log level (0=none, 1=error, 2=warn, 3=info, 4=debug)
#define LOG_LEVEL 3

// =============================================================================
// Example 1: Basic #ifdef and #ifndef
// =============================================================================

// Default buffer size if not defined
#ifndef BUFFER_SIZE
    #define BUFFER_SIZE 1024
#endif

// Default timeout if not defined
#ifndef TIMEOUT_SECONDS
    #define TIMEOUT_SECONDS 30
#endif

// Application name
#ifndef APP_NAME
    #define APP_NAME "ConditionalExample"
#endif

// Debug-only function
#ifdef DEBUG
void debug_print_info(const char *message) {
    printf("[DEBUG] %s\n", message);
    printf("[DEBUG] Buffer size: %d\n", BUFFER_SIZE);
    printf("[DEBUG] Timeout: %d seconds\n", TIMEOUT_SECONDS);
}
#endif

void example_basic_ifdef(void) {
    printf("\n=== Example 1: Basic #ifdef and #ifndef ===\n");
    
    printf("Application: %s\n", APP_NAME);
    printf("Buffer size: %d bytes\n", BUFFER_SIZE);
    printf("Timeout: %d seconds\n", TIMEOUT_SECONDS);
    
#ifdef DEBUG
    printf("\n[DEBUG MODE ENABLED]\n");
    debug_print_info("Initialization complete");
#else
    printf("\n[RELEASE MODE]\n");
#endif

#ifdef VERBOSE
    printf("[VERBOSE] Extra details would appear here\n");
#endif
}

// =============================================================================
// Example 2: #if, #elif, #else for Version Selection
// =============================================================================

#if VERSION == 1
    #define VERSION_STRING "1.0.0"
    #define MAX_ITEMS 100
    #define HAS_ADVANCED_FEATURES 0
#elif VERSION == 2
    #define VERSION_STRING "2.0.0"
    #define MAX_ITEMS 500
    #define HAS_ADVANCED_FEATURES 1
#elif VERSION == 3
    #define VERSION_STRING "3.0.0-beta"
    #define MAX_ITEMS 1000
    #define HAS_ADVANCED_FEATURES 1
    #define HAS_EXPERIMENTAL 1
#else
    #define VERSION_STRING "unknown"
    #define MAX_ITEMS 50
    #define HAS_ADVANCED_FEATURES 0
#endif

void basic_operation(void) {
    printf("  Performing basic operation...\n");
}

#if HAS_ADVANCED_FEATURES
void advanced_operation(void) {
    printf("  Performing advanced operation...\n");
}
#endif

#if defined(HAS_EXPERIMENTAL) && HAS_EXPERIMENTAL
void experimental_operation(void) {
    printf("  Performing experimental operation (use with caution)...\n");
}
#endif

void example_version_selection(void) {
    printf("\n=== Example 2: Version Selection ===\n");
    
    printf("Version: %s\n", VERSION_STRING);
    printf("Max items: %d\n", MAX_ITEMS);
    printf("Advanced features: %s\n", HAS_ADVANCED_FEATURES ? "Yes" : "No");
    
    printf("\nAvailable operations:\n");
    basic_operation();
    
#if HAS_ADVANCED_FEATURES
    advanced_operation();
#endif

#if defined(HAS_EXPERIMENTAL) && HAS_EXPERIMENTAL
    experimental_operation();
#endif
}

// =============================================================================
// Example 3: defined() Operator for Complex Conditions
// =============================================================================

// Multiple conditions with defined()
#if defined(DEBUG) && defined(VERBOSE)
    #define TRACE_ENABLED 1
#else
    #define TRACE_ENABLED 0
#endif

// Either condition
#if defined(DEBUG) || defined(TESTING)
    #define EXTRA_CHECKS 1
#else
    #define EXTRA_CHECKS 0
#endif

// Negation
#if !defined(NDEBUG)
    #define ASSERTIONS_ENABLED 1
#else
    #define ASSERTIONS_ENABLED 0
#endif

#if TRACE_ENABLED
void trace(const char *func, int line) {
    printf("[TRACE] %s at line %d\n", func, line);
}
#define TRACE() trace(__func__, __LINE__)
#else
#define TRACE() ((void)0)
#endif

void example_defined_operator(void) {
    printf("\n=== Example 3: defined() Operator ===\n");
    
    printf("Trace enabled: %s\n", TRACE_ENABLED ? "Yes" : "No");
    printf("Extra checks: %s\n", EXTRA_CHECKS ? "Yes" : "No");
    printf("Assertions enabled: %s\n", ASSERTIONS_ENABLED ? "Yes" : "No");
    
    TRACE();
    printf("Performing some operation...\n");
    TRACE();
}

// =============================================================================
// Example 4: Platform Detection
// =============================================================================

// Detect operating system
#if defined(_WIN32) || defined(_WIN64)
    #define PLATFORM_WINDOWS 1
    #define PLATFORM_NAME "Windows"
#elif defined(__linux__)
    #define PLATFORM_LINUX 1
    #define PLATFORM_NAME "Linux"
#elif defined(__APPLE__) && defined(__MACH__)
    #define PLATFORM_MACOS 1
    #define PLATFORM_NAME "macOS"
#elif defined(__FreeBSD__)
    #define PLATFORM_FREEBSD 1
    #define PLATFORM_NAME "FreeBSD"
#else
    #define PLATFORM_UNKNOWN 1
    #define PLATFORM_NAME "Unknown"
#endif

// Detect architecture
#if defined(__x86_64__) || defined(_M_X64)
    #define ARCH_64BIT 1
    #define ARCH_NAME "x86_64"
#elif defined(__i386__) || defined(_M_IX86)
    #define ARCH_32BIT 1
    #define ARCH_NAME "x86"
#elif defined(__aarch64__) || defined(_M_ARM64)
    #define ARCH_64BIT 1
    #define ARCH_NAME "ARM64"
#elif defined(__arm__) || defined(_M_ARM)
    #define ARCH_32BIT 1
    #define ARCH_NAME "ARM"
#else
    #define ARCH_NAME "Unknown"
#endif

// Detect compiler
#if defined(__GNUC__) && !defined(__clang__)
    #define COMPILER_GCC 1
    #define COMPILER_NAME "GCC"
    #define COMPILER_VERSION __VERSION__
#elif defined(__clang__)
    #define COMPILER_CLANG 1
    #define COMPILER_NAME "Clang"
    #define COMPILER_VERSION __clang_version__
#elif defined(_MSC_VER)
    #define COMPILER_MSVC 1
    #define COMPILER_NAME "MSVC"
    #define COMPILER_VERSION_NUM _MSC_VER
#else
    #define COMPILER_NAME "Unknown"
    #define COMPILER_VERSION "Unknown"
#endif

// Platform-specific path separator
#ifdef PLATFORM_WINDOWS
    #define PATH_SEPARATOR '\\'
    #define PATH_SEPARATOR_STR "\\"
#else
    #define PATH_SEPARATOR '/'
    #define PATH_SEPARATOR_STR "/"
#endif

void example_platform_detection(void) {
    printf("\n=== Example 4: Platform Detection ===\n");
    
    printf("Operating System: %s\n", PLATFORM_NAME);
    printf("Architecture: %s\n", ARCH_NAME);
    printf("Compiler: %s\n", COMPILER_NAME);
    
#ifdef COMPILER_VERSION
    printf("Compiler Version: %s\n", COMPILER_VERSION);
#endif

#ifdef COMPILER_VERSION_NUM
    printf("MSVC Version Number: %d\n", COMPILER_VERSION_NUM);
#endif

    printf("Path separator: '%c'\n", PATH_SEPARATOR);
    
    // Platform-specific behavior
#ifdef PLATFORM_WINDOWS
    printf("\nRunning Windows-specific code...\n");
#elif defined(PLATFORM_LINUX)
    printf("\nRunning Linux-specific code...\n");
#elif defined(PLATFORM_MACOS)
    printf("\nRunning macOS-specific code...\n");
#else
    printf("\nRunning generic code...\n");
#endif
}

// =============================================================================
// Example 5: C Standard Version Detection
// =============================================================================

#ifdef __STDC__
    #define IS_ANSI_C 1
#else
    #define IS_ANSI_C 0
#endif

#ifdef __STDC_VERSION__
    #if __STDC_VERSION__ >= 201710L
        #define C_STANDARD "C17"
        #define C17_AVAILABLE 1
    #elif __STDC_VERSION__ >= 201112L
        #define C_STANDARD "C11"
        #define C11_AVAILABLE 1
    #elif __STDC_VERSION__ >= 199901L
        #define C_STANDARD "C99"
        #define C99_AVAILABLE 1
    #else
        #define C_STANDARD "C95"
    #endif
#else
    #define C_STANDARD "C89/C90"
#endif

// Use C11 features if available
#ifdef C11_AVAILABLE
    #define STATIC_ASSERT(cond, msg) _Static_assert(cond, msg)
#else
    #define STATIC_ASSERT(cond, msg) \
        typedef char static_assert_##__LINE__[(cond) ? 1 : -1]
#endif

// Compile-time assertion example
STATIC_ASSERT(sizeof(int) >= 4, "int must be at least 4 bytes");

void example_c_standard(void) {
    printf("\n=== Example 5: C Standard Version ===\n");
    
    printf("ANSI C compliant: %s\n", IS_ANSI_C ? "Yes" : "No");
    printf("C Standard: %s\n", C_STANDARD);
    
#ifdef __STDC_VERSION__
    printf("__STDC_VERSION__: %ldL\n", __STDC_VERSION__);
#endif

    printf("\nAvailable features:\n");
#ifdef C99_AVAILABLE
    printf("  - C99 features (inline, _Bool, designated initializers)\n");
#endif
#ifdef C11_AVAILABLE
    printf("  - C11 features (_Static_assert, _Generic, _Alignas)\n");
#endif
#ifdef C17_AVAILABLE
    printf("  - C17 features (bug fixes, clarifications)\n");
#endif
}

// =============================================================================
// Example 6: Debug and Logging Configuration
// =============================================================================

// Log level macros
#if LOG_LEVEL >= 1
    #define LOG_ERROR(fmt, ...) \
        fprintf(stderr, "[ERROR] " fmt "\n", ##__VA_ARGS__)
#else
    #define LOG_ERROR(fmt, ...) ((void)0)
#endif

#if LOG_LEVEL >= 2
    #define LOG_WARN(fmt, ...) \
        fprintf(stderr, "[WARN]  " fmt "\n", ##__VA_ARGS__)
#else
    #define LOG_WARN(fmt, ...) ((void)0)
#endif

#if LOG_LEVEL >= 3
    #define LOG_INFO(fmt, ...) \
        printf("[INFO]  " fmt "\n", ##__VA_ARGS__)
#else
    #define LOG_INFO(fmt, ...) ((void)0)
#endif

#if LOG_LEVEL >= 4
    #define LOG_DEBUG(fmt, ...) \
        printf("[DEBUG] " fmt "\n", ##__VA_ARGS__)
#else
    #define LOG_DEBUG(fmt, ...) ((void)0)
#endif

// Debug-only assertions
#ifdef DEBUG
    #define DEBUG_ASSERT(cond) do { \
        if (!(cond)) { \
            fprintf(stderr, "DEBUG_ASSERT failed: %s\n", #cond); \
            fprintf(stderr, "  File: %s, Line: %d\n", __FILE__, __LINE__); \
        } \
    } while(0)
#else
    #define DEBUG_ASSERT(cond) ((void)0)
#endif

void example_debug_logging(void) {
    printf("\n=== Example 6: Debug and Logging ===\n");
    
    printf("Current log level: %d\n", LOG_LEVEL);
    printf("Active log levels: ");
#if LOG_LEVEL >= 1
    printf("ERROR ");
#endif
#if LOG_LEVEL >= 2
    printf("WARN ");
#endif
#if LOG_LEVEL >= 3
    printf("INFO ");
#endif
#if LOG_LEVEL >= 4
    printf("DEBUG ");
#endif
    printf("\n\n");
    
    LOG_DEBUG("Starting operation (debug)");
    LOG_INFO("Processing data (info)");
    LOG_WARN("Resource usage high (warning)");
    LOG_ERROR("Something went wrong (error)");
    
    int value = 5;
    DEBUG_ASSERT(value > 0);
    DEBUG_ASSERT(value > 100);  // This will fail in debug mode
}

// =============================================================================
// Example 7: Feature Toggles
// =============================================================================

// Feature configuration
#if FEATURE_LOGGING
    void log_message(const char *msg) {
        printf("[LOG] %s\n", msg);
    }
    #define LOG_MSG(msg) log_message(msg)
#else
    #define LOG_MSG(msg) ((void)0)
#endif

#if FEATURE_CACHING
    #define CACHE_SIZE 1000
    static int cache[CACHE_SIZE];
    static int cache_hits = 0;
    static int cache_misses = 0;
    
    void cache_store(int key, int value) {
        if (key >= 0 && key < CACHE_SIZE) {
            cache[key] = value;
        }
    }
    
    int cache_get(int key, int *found) {
        if (key >= 0 && key < CACHE_SIZE) {
            *found = 1;
            cache_hits++;
            return cache[key];
        }
        *found = 0;
        cache_misses++;
        return 0;
    }
    
    void print_cache_stats(void) {
        printf("Cache: %d hits, %d misses\n", cache_hits, cache_misses);
    }
#endif

#if FEATURE_STATISTICS
    static int operation_count = 0;
    static int error_count = 0;
    
    #define STAT_OPERATION() (operation_count++)
    #define STAT_ERROR() (error_count++)
    #define PRINT_STATS() printf("Stats: %d ops, %d errors\n", operation_count, error_count)
#else
    #define STAT_OPERATION() ((void)0)
    #define STAT_ERROR() ((void)0)
    #define PRINT_STATS() ((void)0)
#endif

void example_feature_toggles(void) {
    printf("\n=== Example 7: Feature Toggles ===\n");
    
    printf("Features enabled:\n");
    printf("  Logging: %s\n", FEATURE_LOGGING ? "Yes" : "No");
    printf("  Caching: %s\n", FEATURE_CACHING ? "Yes" : "No");
    printf("  Statistics: %s\n", FEATURE_STATISTICS ? "Yes" : "No");
    printf("\n");
    
    // Use logging feature
    LOG_MSG("Starting feature toggle demonstration");
    
    // Use caching feature
#if FEATURE_CACHING
    cache_store(1, 100);
    cache_store(2, 200);
    
    int found;
    int value = cache_get(1, &found);
    if (found) {
        printf("Cache hit: key=1, value=%d\n", value);
    }
    
    cache_get(999, &found);  // Miss
    
    print_cache_stats();
#endif

    // Use statistics feature
    STAT_OPERATION();
    STAT_OPERATION();
    STAT_ERROR();
    PRINT_STATS();
    
    LOG_MSG("Feature toggle demonstration complete");
}

// =============================================================================
// Example 8: Conditional Type Definitions
// =============================================================================

// Boolean type for pre-C99
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
    #include <stdbool.h>
#else
    typedef enum { false = 0, true = 1 } bool;
#endif

// Fixed-width integers
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
    #include <stdint.h>
#else
    // Fallback definitions
    typedef signed char int8_t;
    typedef unsigned char uint8_t;
    typedef signed short int16_t;
    typedef unsigned short uint16_t;
    typedef signed int int32_t;
    typedef unsigned int uint32_t;
#endif

// Size-dependent types
#ifdef ARCH_64BIT
    typedef uint64_t uintmax_custom_t;
    #define UINTMAX_FORMAT "%lu"
#else
    typedef uint32_t uintmax_custom_t;
    #define UINTMAX_FORMAT "%u"
#endif

void example_conditional_types(void) {
    printf("\n=== Example 8: Conditional Type Definitions ===\n");
    
    bool flag = true;
    printf("Boolean flag: %s\n", flag ? "true" : "false");
    
    printf("\nType sizes:\n");
    printf("  int8_t:  %zu bytes\n", sizeof(int8_t));
    printf("  int16_t: %zu bytes\n", sizeof(int16_t));
    printf("  int32_t: %zu bytes\n", sizeof(int32_t));
    
#ifdef ARCH_64BIT
    printf("  int64_t: %zu bytes (64-bit architecture)\n", sizeof(int64_t));
#endif
    
    uintmax_custom_t big_value = 1000000;
    printf("\nCustom max type value: " UINTMAX_FORMAT "\n", big_value);
}

// =============================================================================
// Example 9: Compiler-Specific Attributes
// =============================================================================

// Function attributes
#if defined(__GNUC__) || defined(__clang__)
    #define UNUSED_PARAM __attribute__((unused))
    #define DEPRECATED __attribute__((deprecated))
    #define NORETURN __attribute__((noreturn))
    #define PRINTF_FORMAT(fmt, args) __attribute__((format(printf, fmt, args)))
    #define ALWAYS_INLINE __attribute__((always_inline)) inline
    #define LIKELY(x) __builtin_expect(!!(x), 1)
    #define UNLIKELY(x) __builtin_expect(!!(x), 0)
#elif defined(_MSC_VER)
    #define UNUSED_PARAM
    #define DEPRECATED __declspec(deprecated)
    #define NORETURN __declspec(noreturn)
    #define PRINTF_FORMAT(fmt, args)
    #define ALWAYS_INLINE __forceinline
    #define LIKELY(x) (x)
    #define UNLIKELY(x) (x)
#else
    #define UNUSED_PARAM
    #define DEPRECATED
    #define NORETURN
    #define PRINTF_FORMAT(fmt, args)
    #define ALWAYS_INLINE inline
    #define LIKELY(x) (x)
    #define UNLIKELY(x) (x)
#endif

// Example function with unused parameter
void function_with_unused(int used, int UNUSED_PARAM unused) {
    printf("Used parameter: %d\n", used);
}

// Example with printf format checking
PRINTF_FORMAT(1, 2)
void custom_printf(const char *fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vprintf(fmt, args);
    va_end(args);
}

// Branch prediction example
int process_value(int value) {
    if (LIKELY(value > 0)) {
        return value * 2;  // Common case
    } else {
        return -1;  // Rare case
    }
}

void example_compiler_attributes(void) {
    printf("\n=== Example 9: Compiler-Specific Attributes ===\n");
    
    function_with_unused(42, 0);
    
    custom_printf("Custom printf: value = %d\n", 123);
    
    printf("Process positive: %d\n", process_value(10));
    printf("Process negative: %d\n", process_value(-5));
}

// =============================================================================
// Example 10: Build Configuration Summary
// =============================================================================

// Collect all configuration into a summary
void print_build_configuration(void) {
    printf("\n");
    printf("============================================================\n");
    printf("              BUILD CONFIGURATION SUMMARY                   \n");
    printf("============================================================\n");
    
    printf("\nCompiler Information:\n");
    printf("  Compiler: %s\n", COMPILER_NAME);
#ifdef COMPILER_VERSION
    printf("  Version: %s\n", COMPILER_VERSION);
#endif
    printf("  C Standard: %s\n", C_STANDARD);
    
    printf("\nPlatform Information:\n");
    printf("  OS: %s\n", PLATFORM_NAME);
    printf("  Architecture: %s\n", ARCH_NAME);
    
    printf("\nBuild Mode:\n");
#ifdef DEBUG
    printf("  Mode: DEBUG\n");
#else
    printf("  Mode: RELEASE\n");
#endif
    printf("  Log Level: %d\n", LOG_LEVEL);
    
    printf("\nConfiguration Values:\n");
    printf("  Buffer Size: %d\n", BUFFER_SIZE);
    printf("  Timeout: %d seconds\n", TIMEOUT_SECONDS);
    printf("  Version: %s\n", VERSION_STRING);
    printf("  Max Items: %d\n", MAX_ITEMS);
    
    printf("\nFeature Flags:\n");
    printf("  FEATURE_LOGGING: %s\n", FEATURE_LOGGING ? "ON" : "OFF");
    printf("  FEATURE_CACHING: %s\n", FEATURE_CACHING ? "ON" : "OFF");
    printf("  FEATURE_STATISTICS: %s\n", FEATURE_STATISTICS ? "ON" : "OFF");
    printf("  HAS_ADVANCED_FEATURES: %s\n", HAS_ADVANCED_FEATURES ? "ON" : "OFF");
    
    printf("\nOptional Features:\n");
#ifdef VERBOSE
    printf("  VERBOSE: ON\n");
#else
    printf("  VERBOSE: OFF\n");
#endif

#ifdef TRACE_ENABLED
    printf("  TRACE: %s\n", TRACE_ENABLED ? "ON" : "OFF");
#endif

#ifdef EXTRA_CHECKS
    printf("  EXTRA_CHECKS: %s\n", EXTRA_CHECKS ? "ON" : "OFF");
#endif

    printf("\n============================================================\n");
}

// =============================================================================
// Example 11: Error Directive for Invalid Configurations
// =============================================================================

// These would cause compilation errors if conditions aren't met
// Uncomment to test

/*
#if !defined(VERSION) || VERSION < 1
    #error "VERSION must be defined and >= 1"
#endif

#if LOG_LEVEL < 0 || LOG_LEVEL > 4
    #error "LOG_LEVEL must be between 0 and 4"
#endif

#if defined(FEATURE_DEBUG_ONLY) && !defined(DEBUG)
    #error "FEATURE_DEBUG_ONLY requires DEBUG mode"
#endif
*/

void example_error_directive(void) {
    printf("\n=== Example 11: #error Directive ===\n");
    printf("The #error directive can be used to catch invalid configurations.\n");
    printf("Example:\n");
    printf("  #if !defined(VERSION)\n");
    printf("      #error \"VERSION must be defined\"\n");
    printf("  #endif\n");
    printf("\nThis causes a compile-time error if the condition is met.\n");
}

// =============================================================================
// Example 12: Warning Directive (GCC/Clang)
// =============================================================================

#ifdef DEBUG
    // This generates a warning during compilation
    // #warning "Debug mode is enabled - not for production use"
#endif

// Deprecation warning
#if defined(__GNUC__)
    // #warning is a GCC extension
    // Can be used to flag deprecated code paths
#endif

void example_warning_directive(void) {
    printf("\n=== Example 12: #warning Directive ===\n");
    printf("The #warning directive (GCC/Clang extension) generates\n");
    printf("a warning message during compilation without stopping.\n");
    printf("\nExample:\n");
    printf("  #warning \"This code is deprecated\"\n");
}

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

int main(void) {
    printf("============================================================\n");
    printf("       CONDITIONAL COMPILATION IN C - EXAMPLES              \n");
    printf("============================================================\n");
    
    example_basic_ifdef();
    example_version_selection();
    example_defined_operator();
    example_platform_detection();
    example_c_standard();
    example_debug_logging();
    example_feature_toggles();
    example_conditional_types();
    example_compiler_attributes();
    example_error_directive();
    example_warning_directive();
    
    print_build_configuration();
    
    printf("\n============================================================\n");
    printf("                  ALL EXAMPLES COMPLETED                     \n");
    printf("============================================================\n");
    printf("\nTry recompiling with different flags:\n");
    printf("  gcc -DDEBUG -DVERBOSE examples.c\n");
    printf("  gcc -DVERSION=3 examples.c\n");
    printf("  gcc -DLOG_LEVEL=4 examples.c\n");
    
    return 0;
}
Examples - C Programming Tutorial | DeepML