c
examples
examples.c🔧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;
}