c

exercises

exercises.c🔧
/**
 * =============================================================================
 * Conditional Compilation in C - Exercises
 * =============================================================================
 * 
 * Practice exercises for conditional compilation techniques.
 * Complete each exercise by adding the appropriate preprocessor directives.
 * 
 * Compile with different flags to test:
 *   gcc -Wall -Wextra -std=c99 -o exercises exercises.c
 *   gcc -DDEBUG -o exercises_debug exercises.c
 *   gcc -DPLATFORM_LINUX -o exercises_linux exercises.c
 * 
 * =============================================================================
 */

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

// =============================================================================
// Exercise 1: Basic Conditional Compilation
// =============================================================================
/**
 * Define the following using #ifdef, #ifndef, and #define:
 * 
 * 1. If DEBUG is defined, define DEBUG_MODE as 1, otherwise as 0
 * 2. If MAX_USERS is not defined, set a default of 100
 * 3. If TIMEOUT is not defined, set a default of 30
 * 4. Create a DEBUG_PRINT macro that only prints when DEBUG is defined
 */

// YOUR CODE HERE


void exercise1(void) {
    printf("=== Exercise 1: Basic Conditional Compilation ===\n");
    
    // These should work after implementing the macros
    // printf("DEBUG_MODE: %d\n", DEBUG_MODE);
    // printf("MAX_USERS: %d\n", MAX_USERS);
    // printf("TIMEOUT: %d\n", TIMEOUT);
    
    // This should only print in debug mode
    // DEBUG_PRINT("This is a debug message");
    
    printf("\n");
}

// =============================================================================
// Exercise 2: Multi-level Log System
// =============================================================================
/**
 * Create a configurable logging system using conditional compilation:
 * 
 * 1. Define LOG_LEVEL (if not already defined) with a default of 2
 * 2. Create these logging macros based on LOG_LEVEL:
 *    - LOG_ERROR (level >= 1)
 *    - LOG_WARN  (level >= 2)
 *    - LOG_INFO  (level >= 3)
 *    - LOG_DEBUG (level >= 4)
 * 3. Each macro should print: [LEVEL] message
 * 4. If LOG_LEVEL is 0, all logging should be disabled
 */

// YOUR CODE HERE


void exercise2(void) {
    printf("=== Exercise 2: Multi-level Log System ===\n");
    
    // Uncomment after implementing
    // printf("Current LOG_LEVEL: %d\n\n", LOG_LEVEL);
    
    // LOG_ERROR("This is an error message");
    // LOG_WARN("This is a warning message");
    // LOG_INFO("This is an info message");
    // LOG_DEBUG("This is a debug message");
    
    printf("\n");
}

// =============================================================================
// Exercise 3: Platform Detection
// =============================================================================
/**
 * Create platform detection macros:
 * 
 * 1. Detect if running on Windows, Linux, or macOS
 * 2. Define PLATFORM_NAME as a string ("Windows", "Linux", "macOS", "Unknown")
 * 3. Define PATH_SEP as the path separator ('\\' for Windows, '/' for others)
 * 4. Define a NEWLINE macro ("\r\n" for Windows, "\n" for others)
 * 5. Create a platform_init() function with platform-specific code
 */

// YOUR CODE HERE


void exercise3(void) {
    printf("=== Exercise 3: Platform Detection ===\n");
    
    // Uncomment after implementing
    // printf("Platform: %s\n", PLATFORM_NAME);
    // printf("Path separator: '%c'\n", PATH_SEP);
    // printf("Newline: %s (escaped)\n", "...");
    
    // platform_init();
    
    printf("\n");
}

// =============================================================================
// Exercise 4: Feature Toggles
// =============================================================================
/**
 * Implement a feature toggle system:
 * 
 * 1. Define feature flags: FEATURE_A (1), FEATURE_B (0), FEATURE_C (1)
 * 2. Create FEATURE_ENABLED(x) macro to check if a feature is enabled
 * 3. Conditionally include code only when specific features are enabled
 * 4. Create a function that prints which features are active
 */

// YOUR CODE HERE


void exercise4(void) {
    printf("=== Exercise 4: Feature Toggles ===\n");
    
    // Uncomment after implementing
    // printf("Feature A: %s\n", FEATURE_ENABLED(FEATURE_A) ? "Enabled" : "Disabled");
    // printf("Feature B: %s\n", FEATURE_ENABLED(FEATURE_B) ? "Enabled" : "Disabled");
    // printf("Feature C: %s\n", FEATURE_ENABLED(FEATURE_C) ? "Enabled" : "Disabled");
    
    // print_active_features();
    
    printf("\n");
}

// =============================================================================
// Exercise 5: Version-Based Compilation
// =============================================================================
/**
 * Create version-based feature availability:
 * 
 * 1. Define APP_VERSION as a number (e.g., 200 for version 2.0.0)
 * 2. Based on version:
 *    - Version < 100: Define LEGACY_MODE
 *    - Version >= 100: Define MODERN_MODE
 *    - Version >= 200: Also define ADVANCED_FEATURES
 *    - Version >= 300: Also define EXPERIMENTAL_FEATURES
 * 3. Create functions that exist only in certain versions
 */

// YOUR CODE HERE


void exercise5(void) {
    printf("=== Exercise 5: Version-Based Compilation ===\n");
    
    // Uncomment after implementing
    // printf("App Version: %d\n", APP_VERSION);
    
    // #ifdef LEGACY_MODE
    //     printf("Running in legacy mode\n");
    // #endif
    
    // #ifdef MODERN_MODE
    //     printf("Running in modern mode\n");
    // #endif
    
    // #ifdef ADVANCED_FEATURES
    //     printf("Advanced features available\n");
    // #endif
    
    // #ifdef EXPERIMENTAL_FEATURES
    //     printf("Experimental features available\n");
    // #endif
    
    printf("\n");
}

// =============================================================================
// Exercise 6: Compiler Detection
// =============================================================================
/**
 * Create compiler detection macros:
 * 
 * 1. Detect GCC, Clang, or MSVC
 * 2. Define COMPILER_NAME string
 * 3. Define compiler-specific warning disable macros
 * 4. Create portable UNUSED macro for unused parameters
 * 5. Create portable DEPRECATED macro for deprecated functions
 */

// YOUR CODE HERE


void exercise6(void) {
    printf("=== Exercise 6: Compiler Detection ===\n");
    
    // Uncomment after implementing
    // printf("Compiler: %s\n", COMPILER_NAME);
    
    // Example usage:
    // void deprecated_function(void) DEPRECATED;
    // void func_with_unused(int used, int UNUSED unused);
    
    printf("\n");
}

// =============================================================================
// Exercise 7: Assert System
// =============================================================================
/**
 * Create a custom assertion system:
 * 
 * 1. ASSERT(condition) - basic assertion
 * 2. ASSERT_MSG(condition, msg) - assertion with message
 * 3. STATIC_ASSERT(condition, msg) - compile-time assertion
 * 4. In DEBUG mode: assertions print error and abort
 * 5. In RELEASE mode: assertions are disabled (no code generated)
 */

// YOUR CODE HERE


void exercise7(void) {
    printf("=== Exercise 7: Assert System ===\n");
    
    // Uncomment after implementing
    // int x = 10;
    // ASSERT(x > 0);                         // Should pass
    // ASSERT_MSG(x < 100, "x is too large"); // Should pass
    
    // This would fail in debug mode:
    // ASSERT(x > 100);
    
    // Static assert (compile-time):
    // STATIC_ASSERT(sizeof(int) >= 4, "int must be at least 4 bytes");
    
    printf("\n");
}

// =============================================================================
// Exercise 8: Build Mode Configuration
// =============================================================================
/**
 * Create build mode configurations:
 * 
 * 1. Define three build modes: DEBUG, TEST, RELEASE
 * 2. Only one mode should be active at a time
 * 3. Each mode should configure:
 *    - OPTIMIZATION_LEVEL (0, 1, or 2)
 *    - LOGGING_ENABLED (1 or 0)
 *    - ASSERTIONS_ENABLED (1 or 0)
 *    - BUILD_MODE_NAME (string)
 * 4. Use #error if no mode or multiple modes are defined
 */

// YOUR CODE HERE
// Note: Comment out the #error checks for the exercise to compile


void exercise8(void) {
    printf("=== Exercise 8: Build Mode Configuration ===\n");
    
    // Uncomment after implementing
    // printf("Build Mode: %s\n", BUILD_MODE_NAME);
    // printf("Optimization Level: %d\n", OPTIMIZATION_LEVEL);
    // printf("Logging: %s\n", LOGGING_ENABLED ? "Enabled" : "Disabled");
    // printf("Assertions: %s\n", ASSERTIONS_ENABLED ? "Enabled" : "Disabled");
    
    printf("\n");
}

// =============================================================================
// Exercise 9: Conditional Function Implementation
// =============================================================================
/**
 * Create functions with conditional implementations:
 * 
 * 1. Define USE_FAST_MATH or USE_PRECISE_MATH
 * 2. Implement calculate_sqrt() differently based on the flag
 * 3. Implement sort_array() using quicksort or bubblesort based on a flag
 * 4. Use #warning to indicate which implementation is being used
 */

// YOUR CODE HERE


void exercise9(void) {
    printf("=== Exercise 9: Conditional Function Implementation ===\n");
    
    // Uncomment after implementing
    // double result = calculate_sqrt(16.0);
    // printf("sqrt(16) = %.4f\n", result);
    
    // int arr[] = {5, 2, 8, 1, 9};
    // sort_array(arr, 5);
    // printf("Sorted: ");
    // for (int i = 0; i < 5; i++) printf("%d ", arr[i]);
    // printf("\n");
    
    printf("\n");
}

// =============================================================================
// Exercise 10: Complete Configuration System
// =============================================================================
/**
 * Create a complete configuration system:
 * 
 * 1. Define configuration macros for:
 *    - Memory limits (STACK_SIZE, HEAP_SIZE)
 *    - Threading (MAX_THREADS, THREAD_STACK_SIZE)
 *    - Network (MAX_CONNECTIONS, BUFFER_SIZE)
 *    - Features (ENABLE_SSL, ENABLE_COMPRESSION)
 * 
 * 2. Provide defaults for all values
 * 3. Validate configuration with #error for invalid combinations
 * 4. Create a print_configuration() function
 */

// YOUR CODE HERE


void exercise10(void) {
    printf("=== Exercise 10: Complete Configuration System ===\n");
    
    // Uncomment after implementing
    // print_configuration();
    
    printf("\n");
}

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

int main(void) {
    printf("============================================================\n");
    printf("       CONDITIONAL COMPILATION - EXERCISES                  \n");
    printf("============================================================\n\n");
    
    exercise1();
    exercise2();
    exercise3();
    exercise4();
    exercise5();
    exercise6();
    exercise7();
    exercise8();
    exercise9();
    exercise10();
    
    printf("============================================================\n");
    printf("Complete the exercises by implementing the preprocessor\n");
    printf("directives. Test with different compiler flags!\n");
    printf("============================================================\n");
    
    return 0;
}

// =============================================================================
// ANSWER KEY
// =============================================================================
/*
 * Below are the solutions. Try to solve the exercises yourself first!
 */

/*
// Exercise 1: Basic Conditional Compilation

#ifdef DEBUG
    #define DEBUG_MODE 1
    #define DEBUG_PRINT(msg) printf("[DEBUG] %s\n", msg)
#else
    #define DEBUG_MODE 0
    #define DEBUG_PRINT(msg) ((void)0)
#endif

#ifndef MAX_USERS
    #define MAX_USERS 100
#endif

#ifndef TIMEOUT
    #define TIMEOUT 30
#endif

// Exercise 2: Multi-level Log System

#ifndef LOG_LEVEL
    #define LOG_LEVEL 2
#endif

#if LOG_LEVEL >= 1
    #define LOG_ERROR(msg) printf("[ERROR] %s\n", msg)
#else
    #define LOG_ERROR(msg) ((void)0)
#endif

#if LOG_LEVEL >= 2
    #define LOG_WARN(msg) printf("[WARN]  %s\n", msg)
#else
    #define LOG_WARN(msg) ((void)0)
#endif

#if LOG_LEVEL >= 3
    #define LOG_INFO(msg) printf("[INFO]  %s\n", msg)
#else
    #define LOG_INFO(msg) ((void)0)
#endif

#if LOG_LEVEL >= 4
    #define LOG_DEBUG(msg) printf("[DEBUG] %s\n", msg)
#else
    #define LOG_DEBUG(msg) ((void)0)
#endif

// Exercise 3: Platform Detection

#if defined(_WIN32) || defined(_WIN64)
    #define PLATFORM_NAME "Windows"
    #define PATH_SEP '\\'
    #define NEWLINE "\r\n"
#elif defined(__linux__)
    #define PLATFORM_NAME "Linux"
    #define PATH_SEP '/'
    #define NEWLINE "\n"
#elif defined(__APPLE__)
    #define PLATFORM_NAME "macOS"
    #define PATH_SEP '/'
    #define NEWLINE "\n"
#else
    #define PLATFORM_NAME "Unknown"
    #define PATH_SEP '/'
    #define NEWLINE "\n"
#endif

void platform_init(void) {
#if defined(_WIN32)
    printf("Initializing Windows subsystems...\n");
#elif defined(__linux__)
    printf("Initializing Linux subsystems...\n");
#elif defined(__APPLE__)
    printf("Initializing macOS subsystems...\n");
#else
    printf("Initializing generic subsystems...\n");
#endif
}

// Exercise 4: Feature Toggles

#ifndef FEATURE_A
    #define FEATURE_A 1
#endif
#ifndef FEATURE_B
    #define FEATURE_B 0
#endif
#ifndef FEATURE_C
    #define FEATURE_C 1
#endif

#define FEATURE_ENABLED(x) ((x) != 0)

void print_active_features(void) {
    printf("Active features: ");
#if FEATURE_A
    printf("A ");
#endif
#if FEATURE_B
    printf("B ");
#endif
#if FEATURE_C
    printf("C ");
#endif
    printf("\n");
}

// Exercise 5: Version-Based Compilation

#ifndef APP_VERSION
    #define APP_VERSION 200
#endif

#if APP_VERSION < 100
    #define LEGACY_MODE 1
#else
    #define MODERN_MODE 1
#endif

#if APP_VERSION >= 200
    #define ADVANCED_FEATURES 1
#endif

#if APP_VERSION >= 300
    #define EXPERIMENTAL_FEATURES 1
#endif

// Exercise 6: Compiler Detection

#if defined(__GNUC__) && !defined(__clang__)
    #define COMPILER_NAME "GCC"
    #define UNUSED __attribute__((unused))
    #define DEPRECATED __attribute__((deprecated))
#elif defined(__clang__)
    #define COMPILER_NAME "Clang"
    #define UNUSED __attribute__((unused))
    #define DEPRECATED __attribute__((deprecated))
#elif defined(_MSC_VER)
    #define COMPILER_NAME "MSVC"
    #define UNUSED
    #define DEPRECATED __declspec(deprecated)
#else
    #define COMPILER_NAME "Unknown"
    #define UNUSED
    #define DEPRECATED
#endif

// Exercise 7: Assert System

#ifdef DEBUG
    #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)
    
    #define ASSERT_MSG(cond, msg) do { \
        if (!(cond)) { \
            fprintf(stderr, "Assertion failed: %s\n", msg); \
            fprintf(stderr, "Condition: %s\n", #cond); \
            fprintf(stderr, "File: %s, Line: %d\n", __FILE__, __LINE__); \
            abort(); \
        } \
    } while(0)
#else
    #define ASSERT(cond) ((void)0)
    #define ASSERT_MSG(cond, msg) ((void)0)
#endif

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
    #define STATIC_ASSERT(cond, msg) _Static_assert(cond, msg)
#else
    #define STATIC_ASSERT(cond, msg) \
        typedef char static_assert_##__LINE__[(cond) ? 1 : -1]
#endif

// Exercise 8: Build Mode Configuration
// (Define exactly one: BUILD_DEBUG, BUILD_TEST, or BUILD_RELEASE)

#if defined(BUILD_DEBUG)
    #define BUILD_MODE_NAME "Debug"
    #define OPTIMIZATION_LEVEL 0
    #define LOGGING_ENABLED 1
    #define ASSERTIONS_ENABLED 1
#elif defined(BUILD_TEST)
    #define BUILD_MODE_NAME "Test"
    #define OPTIMIZATION_LEVEL 1
    #define LOGGING_ENABLED 1
    #define ASSERTIONS_ENABLED 1
#elif defined(BUILD_RELEASE)
    #define BUILD_MODE_NAME "Release"
    #define OPTIMIZATION_LEVEL 2
    #define LOGGING_ENABLED 0
    #define ASSERTIONS_ENABLED 0
#else
    // Default to debug
    #define BUILD_MODE_NAME "Debug (default)"
    #define OPTIMIZATION_LEVEL 0
    #define LOGGING_ENABLED 1
    #define ASSERTIONS_ENABLED 1
#endif

// Exercise 9: Conditional Function Implementation

#ifndef USE_PRECISE_MATH
    #define USE_FAST_MATH 1
#endif

#include <math.h>

#ifdef USE_FAST_MATH
// Fast approximation
double calculate_sqrt(double x) {
    // Newton-Raphson approximation (fewer iterations)
    double guess = x / 2.0;
    for (int i = 0; i < 5; i++) {
        guess = (guess + x / guess) / 2.0;
    }
    return guess;
}
#else
// Precise calculation
double calculate_sqrt(double x) {
    return sqrt(x);
}
#endif

#ifdef USE_QUICKSORT
void sort_array(int arr[], int n) {
    // Quicksort implementation
    // (simplified for exercise)
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}
#else
void sort_array(int arr[], int n) {
    // Bubblesort (default)
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}
#endif

// Exercise 10: Complete Configuration System

// Memory limits
#ifndef STACK_SIZE
    #define STACK_SIZE (1024 * 1024)  // 1 MB
#endif

#ifndef HEAP_SIZE
    #define HEAP_SIZE (64 * 1024 * 1024)  // 64 MB
#endif

// Threading
#ifndef MAX_THREADS
    #define MAX_THREADS 16
#endif

#ifndef THREAD_STACK_SIZE
    #define THREAD_STACK_SIZE (256 * 1024)  // 256 KB
#endif

// Network
#ifndef MAX_CONNECTIONS
    #define MAX_CONNECTIONS 1000
#endif

#ifndef BUFFER_SIZE
    #define BUFFER_SIZE 4096
#endif

// Features
#ifndef ENABLE_SSL
    #define ENABLE_SSL 1
#endif

#ifndef ENABLE_COMPRESSION
    #define ENABLE_COMPRESSION 1
#endif

// Validation
#if MAX_THREADS < 1
    #error "MAX_THREADS must be at least 1"
#endif

#if BUFFER_SIZE < 256
    #error "BUFFER_SIZE must be at least 256"
#endif

void print_configuration(void) {
    printf("Configuration:\n");
    printf("  Memory:\n");
    printf("    Stack Size: %d bytes\n", STACK_SIZE);
    printf("    Heap Size: %d bytes\n", HEAP_SIZE);
    printf("  Threading:\n");
    printf("    Max Threads: %d\n", MAX_THREADS);
    printf("    Thread Stack: %d bytes\n", THREAD_STACK_SIZE);
    printf("  Network:\n");
    printf("    Max Connections: %d\n", MAX_CONNECTIONS);
    printf("    Buffer Size: %d bytes\n", BUFFER_SIZE);
    printf("  Features:\n");
    printf("    SSL: %s\n", ENABLE_SSL ? "Enabled" : "Disabled");
    printf("    Compression: %s\n", ENABLE_COMPRESSION ? "Enabled" : "Disabled");
}
*/
Exercises - C Programming Tutorial | DeepML