The Complete Guide to C Macros, Preprocessor Directives, and Compiler Attributes

Table of Contents

  1. Introduction to the C Preprocessor
  2. Basic Preprocessor Directives
  3. Conditional Compilation
  4. Macro Definitions and Expansion
  5. Advanced Macro Techniques
  6. Variadic Macros
  7. Token Pasting and Stringification
  8. Predefined Macros
  9. Compiler Attributes - GCC and Clang
  10. Compiler Attributes - MSVC
  11. Cross-Platform Compilation
  12. Architecture Detection
  13. Operating System Detection
  14. Compiler Detection and Capabilities
  15. Linux Kernel Macro Patterns
  16. Container_of and Type-Safe Macros
  17. Likely/Unlikely Branch Hints
  18. Barrier and Atomic Operations
  19. Debugging and Assertion Macros
  20. Complete Cross-Platform Project

Chapter 1: Introduction to the C Preprocessor

1.1 What is the Preprocessor?

The C preprocessor is a text substitution tool that runs before the compiler. It:

  • Processes directives that begin with #
  • Performs text replacement (macros)
  • Handles conditional compilation
  • Includes files
  • Operates on tokens, not C syntax

1.2 Preprocessor Phases

Source Code (.c)

[1. Trigraph Replacement]      ??= becomes #

[2. Line Splicing]             Backslash-newline removed

[3. Tokenization]              Break into tokens

[4. Preprocessor Directives]   #include, #define, #if, etc.

[5. String Concatenation]      "Hello" "World" → "HelloWorld"

Translation Unit

Compiler

1.3 Why Use the Preprocessor?

Benefits:

  • Conditional Compilation - Different code for different platforms
  • Code Reuse - Avoid repetition with macros
  • Configuration - Feature flags and build options
  • Type Safety - Type-generic macros (C11)
  • Performance - Inline expansion without function call overhead

Drawbacks:

  • Hard to Debug - Errors in expanded code
  • Name Collisions - Macros don’t respect scope
  • Multiple Evaluation - Side effects in macro arguments
  • Code Bloat - Large macros expand everywhere

1.4 Viewing Preprocessor Output

# GCC/Clang: Stop after preprocessing
gcc -E source.c -o source.i

# Show only preprocessor output (no line markers)
gcc -E -P source.c

# MSVC: Preprocess only
cl /E source.c

Example:

// test.c
#define MAX(a, b) ((a) > (b) ? (a) : (b))

int main() {
    int x = MAX(5, 10);
    return 0;
}

After preprocessing (gcc -E test.c):

int main() {
    int x = ((5) > (10) ? (5) : (10));
    return 0;
}

Chapter 2: Basic Preprocessor Directives

2.1 File Inclusion - #include

// Angle brackets: Search system include paths
#include <stdio.h>
#include <stdlib.h>

// Quotes: Search current directory first, then system paths
#include "myheader.h"
#include "utils/helpers.h"

// Computed includes (not recommended)
#define HEADER "config.h"
#include HEADER

Include Guard Pattern:

// myheader.h
#ifndef MYHEADER_H
#define MYHEADER_H

// Header contents here
void myFunction(void);

#endif // MYHEADER_H

Modern #pragma once:

// myheader.h
#pragma once  // Simpler, but not standard C

void myFunction(void);

2.2 Macro Definition - #define

// Object-like macro (constant)
#define PI 3.14159265359
#define BUFFER_SIZE 1024
#define MAX_PATH 260

// Function-like macro
#define SQUARE(x) ((x) * (x))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))

// Multi-line macros
#define SWAP(a, b, type) \
    do { \
        type temp = (a); \
        (a) = (b); \
        (b) = temp; \
    } while(0)

// Empty macros for feature detection
#define HAS_FEATURE_X

2.3 Macro Undefinition - #undef

#define TEMP 100

// Use TEMP...

#undef TEMP  // Remove definition

// TEMP is no longer defined
#define TEMP 200  // Can redefine

2.4 Error and Warning Directives

// #error - Stop compilation with message
#ifndef CONFIG_LOADED
#error "Configuration file must be included first!"
#endif

// #warning - Continue with warning (GCC/Clang)
#warning "This code is deprecated"

// Conditional errors
#if __STDC_VERSION__ < 199901L
#error "This code requires C99 or later"
#endif

2.5 Line Control - #line

// Change reported line number and filename
#line 100 "fakefile.c"

// Now errors report line 100 in fakefile.c

// Reset to actual file
#line __LINE__ __FILE__

2.6 Pragma Directive - #pragma

// Compiler-specific directives
#pragma once  // Include guard (non-standard but widely supported)

// Pack structures (MSVC)
#pragma pack(push, 1)
struct PackedStruct {
    char c;
    int i;
};
#pragma pack(pop)

// Disable warnings
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
int unused_var;
#pragma GCC diagnostic pop

// Optimization hints
#pragma GCC optimize("O3")

2.7 Null Directive -

// Empty directive - does nothing, but valid
#

// Can be used to create blank lines in macro expansions

Chapter 3: Conditional Compilation

3.1 Basic Conditionals

// #if - Compile if expression is true (non-zero)
#if 1
    printf("This is always compiled\n");
#endif

#if 0
    printf("This is never compiled\n");
#endif

// Expressions can use operators
#if (VERSION_MAJOR * 100 + VERSION_MINOR) >= 205
    // Version 2.5 or higher
#endif

3.2 #ifdef and #ifndef

// #ifdef - If defined
#define DEBUG

#ifdef DEBUG
    printf("Debug mode enabled\n");
#endif

// #ifndef - If not defined
#ifndef NDEBUG
    assert(x > 0);
#endif

// Common pattern: Header guards
#ifndef CONFIG_H
#define CONFIG_H
    // Header contents
#endif

3.3 #else and #elif

// #else - Alternative branch
#ifdef WINDOWS
    #include <windows.h>
#else
    #include <unistd.h>
#endif

// #elif - Else if
#if defined(__linux__)
    #define OS_NAME "Linux"
#elif defined(__APPLE__)
    #define OS_NAME "macOS"
#elif defined(_WIN32)
    #define OS_NAME "Windows"
#else
    #define OS_NAME "Unknown"
#endif

3.4 Modern #elifdef and #elifndef (C23)

// C23 introduced #elifdef and #elifndef for cleaner code

// Old way (C89-C17)
#ifdef FEATURE_A
    // Code A
#else
    #ifdef FEATURE_B
        // Code B
    #else
        #ifdef FEATURE_C
            // Code C
        #endif
    #endif
#endif

// New way (C23)
#ifdef FEATURE_A
    // Code A
#elifdef FEATURE_B
    // Code B
#elifdef FEATURE_C
    // Code C
#endif

// Also works with ifndef
#ifndef FEATURE_A
    // Code A
#elifndef FEATURE_B
    // Code B
#endif

3.5 defined() Operator

// Check if macro is defined
#if defined(DEBUG)
    printf("Debug enabled\n");
#endif

// Can combine with logical operators
#if defined(DEBUG) && !defined(NDEBUG)
    printf("Full debug mode\n");
#endif

// Multiple conditions
#if defined(__linux__) || defined(__unix__)
    #define UNIX_LIKE 1
#endif

// Equivalent forms
#ifdef DEBUG        // Same as:
#if defined(DEBUG)  // This

#ifndef NDEBUG      // Same as:
#if !defined(NDEBUG) // This

3.6 Complex Conditional Examples

// Feature detection
#if defined(__GNUC__) && __GNUC__ >= 4
    #define HAVE_GCC4_FEATURES 1
#endif

// Platform-specific code
#if defined(_WIN32)
    #define PATH_SEPARATOR '\\'
    #define LINE_ENDING "\r\n"
#elif defined(__unix__) || defined(__APPLE__)
    #define PATH_SEPARATOR '/'
    #define LINE_ENDING "\n"
#else
    #error "Unsupported platform"
#endif

// Version checking
#if __STDC_VERSION__ >= 201112L
    // C11 or later
    #define THREAD_LOCAL _Thread_local
#elif defined(__GNUC__)
    #define THREAD_LOCAL __thread
#elif defined(_MSC_VER)
    #define THREAD_LOCAL __declspec(thread)
#else
    #error "Thread-local storage not supported"
#endif

Chapter 4: Macro Definitions and Expansion

4.1 Object-Like Macros

// Simple constants
#define PI 3.14159265359
#define BUFFER_SIZE 4096
#define VERSION "1.0.0"

// Usage
double area = PI * radius * radius;
char buffer[BUFFER_SIZE];
printf("Version: %s\n", VERSION);

// Expressions
#define MAX_CONNECTIONS (10 * 1024)
#define TIMEOUT_MS (5 * 60 * 1000)  // 5 minutes in milliseconds

// Type aliases (before typedef)
#define BYTE unsigned char
#define WORD unsigned short

4.2 Function-Like Macros

// Basic function macro
#define SQUARE(x) ((x) * (x))

// Parentheses are critical!
#define BAD_SQUARE(x) x * x     // Wrong!
int result = BAD_SQUARE(2 + 3); // Expands to: 2 + 3 * 2 + 3 = 11 (not 25!)

#define GOOD_SQUARE(x) ((x) * (x))  // Correct
int result = GOOD_SQUARE(2 + 3);    // Expands to: ((2 + 3) * (2 + 3)) = 25

// Multiple parameters
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define CLAMP(x, lo, hi) (MIN(MAX(x, lo), hi))

// Common pitfall: Multiple evaluation
int x = 5;
int y = MAX(x++, 10);  // x is incremented TWICE!
// Expands to: ((x++) > (10) ? (x++) : (10))

4.3 Statement Expression Macros (GCC Extension)

// Problem: Multiple statements in a macro
#define BAD_SWAP(a, b) \
    int temp = a; \
    a = b; \
    b = temp;

if (condition)
    BAD_SWAP(x, y);  // Only first statement is in if!
else
    doSomething();

// Solution 1: do-while(0)
#define SWAP(a, b, type) \
    do { \
        type temp = (a); \
        (a) = (b); \
        (b) = temp; \
    } while(0)

if (condition)
    SWAP(x, y, int);  // Works correctly!
else
    doSomething();

// Solution 2: Statement expressions (GCC/Clang only)
#define SWAP_EXPR(a, b, type) \
    ({ \
        type temp = (a); \
        (a) = (b); \
        (b) = temp; \
    })

4.4 Macro Expansion Rules

// Macros expand recursively
#define A 1
#define B A + 1
#define C B + 1

int x = C;  // Expands to: 1 + 1 + 1

// But not self-recursively
#define RECURSIVE RECURSIVE + 1  // Doesn't expand infinitely!
// Expands to: RECURSIVE + 1 (stops after one expansion)

// Expansion order matters
#define FIRST 100
#define SECOND FIRST

#undef FIRST
#define FIRST 200

int x = SECOND;  // Still 100! SECOND was expanded when defined

4.5 Rescanning and Expansion

// Macros are rescanned after expansion
#define PARAM X
#define ARG(a) a

int result = ARG(PARAM);  // Expands to: X

// But arguments are fully expanded before substitution
#define X 5
#define Y X
#define SHOW(x) printf("%d\n", x)

SHOW(Y);  // Expands to: printf("%d\n", 5)

Chapter 5: Advanced Macro Techniques

5.1 X-Macros (Enum-String Mapping)

// Define data once, use multiple times
#define ERROR_CODES(X) \
    X(SUCCESS,        0, "Operation successful") \
    X(ERR_NOMEM,      1, "Out of memory") \
    X(ERR_NOTFOUND,   2, "Not found") \
    X(ERR_INVALID,    3, "Invalid argument") \
    X(ERR_TIMEOUT,    4, "Operation timed out")

// Generate enum
#define ENUM_ENTRY(name, value, desc) name = value,
typedef enum {
    ERROR_CODES(ENUM_ENTRY)
} ErrorCode;
#undef ENUM_ENTRY

// Generate string conversion function
#define STRING_ENTRY(name, value, desc) case name: return #name;
const char* errorToString(ErrorCode err) {
    switch (err) {
        ERROR_CODES(STRING_ENTRY)
        default: return "UNKNOWN";
    }
}
#undef STRING_ENTRY

// Generate description function
#define DESC_ENTRY(name, value, desc) case name: return desc;
const char* errorDescription(ErrorCode err) {
    switch (err) {
        ERROR_CODES(DESC_ENTRY)
        default: return "Unknown error";
    }
}
#undef DESC_ENTRY

// Usage
printf("%s: %s\n", errorToString(ERR_NOMEM), errorDescription(ERR_NOMEM));
// Output: ERR_NOMEM: Out of memory

5.2 Defer and Obstruct Macros

// Empty macro
#define EMPTY()

// Defer expansion
#define DEFER(id) id EMPTY()

// Obstruct expansion
#define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)()

// Evaluate macro multiple times
#define EVAL(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
#define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
#define EVAL2(...) __VA_ARGS__

// Example: Recursive macro that generates code
#define REPEAT(count, macro, ...) \
    REPEAT_HELPER(count, macro, __VA_ARGS__)

// This enables recursive expansion tricks

5.3 Counting Macro Arguments

// Count number of arguments (up to 16)
#define COUNT_ARGS(...) COUNT_ARGS_HELPER(__VA_ARGS__, \
    16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)

#define COUNT_ARGS_HELPER( \
    _1, _2, _3, _4, _5, _6, _7, _8, \
    _9, _10, _11, _12, _13, _14, _15, _16, N, ...) N

// Usage
int count = COUNT_ARGS(a, b, c);  // Returns 3

5.4 Foreach Macro

// Apply macro to each argument
#define FOREACH_1(macro, x) macro(x)
#define FOREACH_2(macro, x, ...) macro(x) FOREACH_1(macro, __VA_ARGS__)
#define FOREACH_3(macro, x, ...) macro(x) FOREACH_2(macro, __VA_ARGS__)
#define FOREACH_4(macro, x, ...) macro(x) FOREACH_3(macro, __VA_ARGS__)

#define GET_MACRO(_1,_2,_3,_4,NAME,...) NAME
#define FOREACH(macro, ...) \
    GET_MACRO(__VA_ARGS__, FOREACH_4, FOREACH_3, FOREACH_2, FOREACH_1) \
    (macro, __VA_ARGS__)

// Example: Print all arguments
#define PRINT_ARG(x) printf("%s = %d\n", #x, x);

int a = 1, b = 2, c = 3;
FOREACH(PRINT_ARG, a, b, c)
// Expands to:
// printf("%s = %d\n", "a", a);
// printf("%s = %d\n", "b", b);
// printf("%s = %d\n", "c", c);

5.5 Type-Generic Macros (C11)

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

int i = 42;
float f = 3.14f;
double d = 2.718;
char* s = "hello";

print_type(i);  // int: 42
print_type(f);  // float: 3.140000
print_type(d);  // double: 2.718000
print_type(s);  // string: hello

// Generic selection for return type
#define max(a, b) _Generic((a) + (b), \
    int: max_int, \
    long: max_long, \
    float: max_float, \
    double: max_double \
)(a, b)

Chapter 6: Variadic Macros

6.1 Basic Variadic Macros

// C99 variadic macros with __VA_ARGS__
#define debug_print(...) \
    fprintf(stderr, "DEBUG: " __VA_ARGS__)

// Usage
debug_print("Value: %d\n", x);
// Expands to: fprintf(stderr, "DEBUG: " "Value: %d\n", x);

// Variadic with fixed parameters
#define log_message(level, ...) \
    printf("[%s] ", level); \
    printf(__VA_ARGS__); \
    printf("\n")

log_message("INFO", "Server started on port %d", 8080);
// Output: [INFO] Server started on port 8080

6.2 VA_OPT (C++20/C23)

// Problem: Trailing comma with empty variadic args
#define LOG(fmt, ...) printf(fmt, __VA_ARGS__)
LOG("Hello");  // Error! Expands to: printf("Hello", )

// Old solution: GCC ##__VA_ARGS__ extension
#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__)
LOG("Hello");  // OK: printf("Hello")

// C23 solution: __VA_OPT__
#define LOG(fmt, ...) printf(fmt __VA_OPT__(,) __VA_ARGS__)
LOG("Hello");        // printf("Hello")
LOG("Value: %d", x); // printf("Value: %d", x)

// More examples
#define CALL_FUNC(func, ...) func(__VA_OPT__(__VA_ARGS__))
CALL_FUNC(foo);      // foo()
CALL_FUNC(foo, 1, 2); // foo(1, 2)

6.3 Named Variadic Arguments (GCC Extension)

// GCC allows naming the variadic part
#define debug(format, args...) \
    fprintf(stderr, "DEBUG: " format, args)

debug("x = %d, y = %d\n", x, y);

6.4 Practical Variadic Examples

// Assert with custom message
#define ASSERT(condition, ...) \
    do { \
        if (!(condition)) { \
            fprintf(stderr, "Assertion failed: %s\n", #condition); \
            fprintf(stderr, "  File: %s, Line: %d\n", __FILE__, __LINE__); \
            fprintf(stderr, "  " __VA_ARGS__); \
            fprintf(stderr, "\n"); \
            abort(); \
        } \
    } while(0)

ASSERT(x > 0, "x must be positive, got: %d", x);

// Logging with levels
#define LOG_ERROR(...) log_message("ERROR", __FILE__, __LINE__, __VA_ARGS__)
#define LOG_WARN(...)  log_message("WARN",  __FILE__, __LINE__, __VA_ARGS__)
#define LOG_INFO(...)  log_message("INFO",  __FILE__, __LINE__, __VA_ARGS__)

void log_message(const char* level, const char* file, int line, 
                 const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    
    printf("[%s] %s:%d - ", level, file, line);
    vprintf(fmt, args);
    printf("\n");
    
    va_end(args);
}

// Usage
LOG_ERROR("Failed to open file: %s", filename);
LOG_INFO("Connection established");

Chapter 7: Token Pasting and Stringification

7.1 Stringification Operator (#)

// Convert macro argument to string literal
#define STRINGIFY(x) #x

const char* str = STRINGIFY(hello);  // "hello"
const char* num = STRINGIFY(123);    // "123"

// Common use: Variable name as string
#define PRINT_VAR(var) printf("%s = %d\n", #var, var)

int count = 42;
PRINT_VAR(count);  // Output: count = 42

// Debug macro
#define DEBUG_EXPR(expr) \
    printf("%s = %d\n", #expr, (expr))

DEBUG_EXPR(2 + 2);  // Output: 2 + 2 = 4

// Note: Stringification happens before expansion!
#define VALUE 100
const char* s = STRINGIFY(VALUE);  // "VALUE", not "100"!

// To expand first, use indirection
#define STRINGIFY_EXPAND(x) STRINGIFY(x)
const char* s = STRINGIFY_EXPAND(VALUE);  // "100"

7.2 Token Pasting Operator (##)

// Concatenate tokens
#define CONCAT(a, b) a##b

int xy = CONCAT(x, y);  // Creates identifier: xy

// Create variable names
#define VAR(name, num) name##num

int VAR(value, 1) = 10;  // int value1 = 10;
int VAR(value, 2) = 20;  // int value2 = 20;

// Generate function names
#define MAKE_FUNC(type) \
    void print_##type(type value) { \
        printf("Value: %d\n", (int)value); \
    }

MAKE_FUNC(int)
MAKE_FUNC(char)

// Creates:
// void print_int(int value) { ... }
// void print_char(char value) { ... }

// Combine with stringification
#define REGISTER_TYPE(type) \
    { \
        .name = #type, \
        .size = sizeof(type), \
        .align = _Alignof(type) \
    }

struct TypeInfo types[] = {
    REGISTER_TYPE(char),
    REGISTER_TYPE(int),
    REGISTER_TYPE(long),
    REGISTER_TYPE(double),
};

7.3 Advanced Token Manipulation

// Create unique identifiers
#define UNIQUE_NAME(base) CONCAT(base, __LINE__)

int UNIQUE_NAME(temp) = 10;  // temp42 (if on line 42)
int UNIQUE_NAME(temp) = 20;  // temp43 (if on line 43)

// Multi-level concatenation
#define CONCAT3(a, b, c) a##b##c

CONCAT3(x, y, z)  // xyz

// Conditional concatenation
#ifdef USE_PREFIX
    #define FUNC_NAME(name) prefix_##name
#else
    #define FUNC_NAME(name) name
#endif

void FUNC_NAME(init)(void);  // prefix_init() or init()

7.4 Common Pitfalls

// Problem: ## suppresses expansion
#define VALUE 100
#define MAKE_NAME(x) var_##x

int MAKE_NAME(VALUE);  // int var_VALUE; (not var_100!)

// Solution: Add indirection level
#define MAKE_NAME_EXPAND(x) var_##x
#define MAKE_NAME(x) MAKE_NAME_EXPAND(x)

int MAKE_NAME(VALUE);  // int var_100;

// Problem: Stringification before expansion
#define VERSION 1.0
#define VERSION_STR #VERSION  // "VERSION"

// Solution: Indirection
#define STRINGIFY(x) #x
#define VERSION_STR STRINGIFY(VERSION)  // "1.0"

Chapter 8: Predefined Macros

8.1 Standard Predefined Macros

// File and line information
__FILE__     // Current source filename: "main.c"
__LINE__     // Current line number: 42
__func__     // Current function name (C99): "myFunction"
__FUNCTION__ // Same as __func__ (GCC/MSVC)

// Date and time (at compilation)
__DATE__     // "Feb 20 2026"
__TIME__     // "14:30:00"

// C standard version
__STDC__           // 1 if ISO C conforming compiler
__STDC_VERSION__   // 199901L (C99), 201112L (C11), 201710L (C17), 202311L (C23)
__STDC_HOSTED__    // 1 for hosted, 0 for freestanding

// Example usage
void logError(const char* msg) {
    fprintf(stderr, "[%s:%d in %s()] %s\n",
            __FILE__, __LINE__, __func__, msg);
}

// Build timestamp
const char* buildDate = __DATE__ " " __TIME__;

8.2 Compiler-Specific Macros

// GCC/Clang
__GNUC__           // Major version: 11
__GNUC_MINOR__     // Minor version: 2
__GNUC_PATCHLEVEL__ // Patch level: 0
__VERSION__        // Version string: "11.2.0"

// Clang
__clang__          // Defined if Clang
__clang_major__    // Major version
__clang_minor__    // Minor version

// MSVC
_MSC_VER           // Version: 1900 (VS2015), 1920 (VS2019)
_MSC_FULL_VER      // Full version
_WIN32             // Defined for 32 and 64-bit Windows
_WIN64             // Defined for 64-bit Windows

// Intel Compiler
__INTEL_COMPILER   // Version number

// Example: Compiler detection
#if defined(__GNUC__)
    #define COMPILER "GCC"
#elif defined(__clang__)
    #define COMPILER "Clang"
#elif defined(_MSC_VER)
    #define COMPILER "MSVC"
#elif defined(__INTEL_COMPILER)
    #define COMPILER "Intel"
#else
    #define COMPILER "Unknown"
#endif

printf("Compiled with: %s\n", COMPILER);

8.3 Architecture Macros

// x86/x64
__i386__           // 32-bit x86 (GCC)
__x86_64__         // 64-bit x86 (GCC)
_M_IX86            // 32-bit x86 (MSVC)
_M_X64             // 64-bit x64 (MSVC)

// ARM
__arm__            // ARM (GCC)
__aarch64__        // ARM64 (GCC)
_M_ARM             // ARM (MSVC)
_M_ARM64           // ARM64 (MSVC)

// PowerPC
__powerpc__        // PowerPC
__powerpc64__      // PowerPC 64-bit

// MIPS
__mips__           // MIPS

// RISC-V
__riscv            // RISC-V

// Example: Pointer size
#if defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || defined(_M_ARM64)
    #define POINTER_SIZE 8
#else
    #define POINTER_SIZE 4
#endif

8.4 OS Detection Macros

// Windows
_WIN32             // Windows 32 or 64
_WIN64             // Windows 64-bit
__CYGWIN__         // Cygwin
__MINGW32__        // MinGW 32-bit
__MINGW64__        // MinGW 64-bit

// Unix/Linux
__unix__           // Unix-like
__linux__          // Linux
__APPLE__          // Any Apple platform
__MACH__           // Mach kernel (macOS/iOS)

// BSD
__FreeBSD__        // FreeBSD
__NetBSD__         // NetBSD
__OpenBSD__        // OpenBSD

// Mobile
__ANDROID__        // Android
__ANDROID_API__    // Android API level

// Example: OS-specific code
#if defined(_WIN32)
    #include <windows.h>
    #define SLEEP_MS(ms) Sleep(ms)
#elif defined(__unix__) || defined(__APPLE__)
    #include <unistd.h>
    #define SLEEP_MS(ms) usleep((ms) * 1000)
#endif

8.5 Feature Test Macros

// POSIX
_POSIX_VERSION     // POSIX version
_POSIX_C_SOURCE    // Requested POSIX features

// GNU
_GNU_SOURCE        // GNU extensions

// BSD
_BSD_SOURCE        // BSD extensions

// X/Open
_XOPEN_SOURCE      // X/Open standard

// Example: Request features
#define _POSIX_C_SOURCE 200809L  // Request POSIX.1-2008
#include <unistd.h>

// Check availability
#ifdef _POSIX_VERSION
    printf("POSIX version: %ld\n", _POSIX_VERSION);
#endif

Chapter 9: Compiler Attributes - GCC and Clang

9.1 Function Attributes

// __attribute__ syntax (GCC/Clang)

// Prevent inlining
__attribute__((noinline))
void debug_function(void) {
    // Never inlined
}

// Force inlining
__attribute__((always_inline))
static inline int add(int a, int b) {
    return a + b;
}

// Mark as pure (no side effects, result depends only on args)
__attribute__((pure))
int compute_hash(const char* str) {
    // Can be optimized aggressively
}

// Mark as const (no side effects, doesn't read memory)
__attribute__((const))
int square(int x) {
    return x * x;  // Pure computation
}

// Noreturn (function never returns)
__attribute__((noreturn))
void fatal_error(const char* msg) {
    fprintf(stderr, "FATAL: %s\n", msg);
    exit(1);
}

// Warn if return value is ignored
__attribute__((warn_unused_result))
int open_file(const char* path) {
    // Compiler warns if caller ignores return value
}

// Format string checking (printf-like)
__attribute__((format(printf, 1, 2)))
void my_printf(const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vprintf(fmt, args);
    va_end(args);
}

// Custom format
__attribute__((format(scanf, 2, 3)))
int my_scanf(FILE* f, const char* fmt, ...) {
    // Format string is arg 2, varargs start at 3
}

9.2 Variable Attributes

// Alignment
__attribute__((aligned(16)))
float vector[4];  // Align to 16-byte boundary

// Packed (no padding)
struct __attribute__((packed)) PackedStruct {
    char c;
    int i;   // No padding between c and i
    short s;
};

// Section placement
__attribute__((section(".mysection")))
int special_var = 42;

// Unused (suppress warnings)
__attribute__((unused))
static int debug_var;

// Deprecated
__attribute__((deprecated("Use new_function instead")))
void old_function(void) {
    // Compiler warns when used
}

// Visibility (shared libraries)
__attribute__((visibility("default")))
void public_api(void);

__attribute__((visibility("hidden")))
void internal_function(void);

// Weak symbol (can be overridden)
__attribute__((weak))
void default_handler(void) {
    // Default implementation
}

// Alias
__attribute__((alias("real_function")))
void aliased_function(void);

// Constructor/Destructor (run before/after main)
__attribute__((constructor))
void init_before_main(void) {
    printf("Runs before main!\n");
}

__attribute__((destructor))
void cleanup_after_main(void) {
    printf("Runs after main!\n");
}

9.3 Type Attributes

// Transparent union (for overloaded functions)
typedef union __attribute__((transparent_union)) {
    int* int_ptr;
    float* float_ptr;
} GenericPtr;

void process(GenericPtr ptr);

// Can call with either type
int x;
float y;
process((GenericPtr){.int_ptr = &x});
process((GenericPtr){.float_ptr = &y});

// May alias (disable strict aliasing for this type)
typedef int __attribute__((__may_alias__)) aliasing_int;

// Designated init (require designated initializers)
struct __attribute__((designated_init)) Config {
    int width;
    int height;
};

struct Config cfg = {.width = 800, .height = 600};  // OK
struct Config cfg2 = {800, 600};  // Warning!

9.4 Common Attribute Macros

// Create portable macros
#if defined(__GNUC__) || defined(__clang__)
    #define LIKELY(x)   __builtin_expect(!!(x), 1)
    #define UNLIKELY(x) __builtin_expect(!!(x), 0)
    #define PACKED      __attribute__((packed))
    #define ALIGNED(n)  __attribute__((aligned(n)))
    #define NORETURN    __attribute__((noreturn))
    #define UNUSED      __attribute__((unused))
    #define PURE        __attribute__((pure))
    #define CONST       __attribute__((const))
#elif defined(_MSC_VER)
    #define LIKELY(x)   (x)
    #define UNLIKELY(x) (x)
    #define PACKED      // MSVC uses #pragma pack
    #define ALIGNED(n)  __declspec(align(n))
    #define NORETURN    __declspec(noreturn)
    #define UNUSED
    #define PURE
    #define CONST
#else
    #define LIKELY(x)   (x)
    #define UNLIKELY(x) (x)
    #define PACKED
    #define ALIGNED(n)
    #define NORETURN
    #define UNUSED
    #define PURE
    #define CONST
#endif

// Usage
if (LIKELY(ptr != NULL)) {
    // Hot path
}

struct PACKED {
    char c;
    int i;
} packed_data;

ALIGNED(64) char cache_line[64];

Chapter 10: Compiler Attributes - MSVC

10.1 MSVC __declspec Attributes

// DLL import/export
__declspec(dllexport) void exported_function(void);
__declspec(dllimport) void imported_function(void);

// Common pattern
#ifdef BUILDING_DLL
    #define API_EXPORT __declspec(dllexport)
#else
    #define API_EXPORT __declspec(dllimport)
#endif

API_EXPORT void my_api_function(void);

// Alignment
__declspec(align(16)) float vector[4];

// Noreturn
__declspec(noreturn) void fatal_error(const char* msg);

// Thread-local storage
__declspec(thread) int thread_local_var;

// Deprecated
__declspec(deprecated("Use new_function instead"))
void old_function(void);

// Naked (no prolog/epilog)
__declspec(naked) void asm_function(void) {
    __asm {
        mov eax, 42
        ret
    }
}

// No throw (C++ compatible)
__declspec(nothrow) void safe_function(void);

// Restrict (pointer aliasing)
void process(__declspec(restrict) int* data);

// Selectany (weak external)
__declspec(selectany) int weak_var = 0;

// UUID (COM)
struct __declspec(uuid("12345678-1234-1234-1234-123456789ABC"))
    MyInterface;

10.2 MSVC Pragmas

// Structure packing
#pragma pack(push, 1)
struct PackedStruct {
    char c;
    int i;
};
#pragma pack(pop)

// Warning control
#pragma warning(push)
#pragma warning(disable: 4996)  // Disable specific warning
// Code that generates warnings
#pragma warning(pop)

// Optimization
#pragma optimize("", off)
// Code with optimizations disabled
#pragma optimize("", on)

// Inline
#pragma inline_depth(8)
#pragma inline_recursion(on)

// Link directives
#pragma comment(lib, "user32.lib")
#pragma comment(linker, "/subsystem:console")

// Section
#pragma section(".mysection", read, write)
__declspec(allocate(".mysection")) int my_var;

// Message at compile time
#pragma message("Compiling with feature X enabled")

// Once (header guard)
#pragma once

10.3 MSVC Intrinsics

#include <intrin.h>

// Bit manipulation
unsigned long index;
if (_BitScanForward(&index, value)) {
    // index = position of first set bit
}

// Atomic operations
long result = _InterlockedIncrement(&counter);
long old = _InterlockedCompareExchange(&var, new_val, old_val);

// CPU barriers
_ReadWriteBarrier();   // Compiler barrier
_mm_mfence();          // Memory fence

// Prefetch
_mm_prefetch(ptr, _MM_HINT_T0);

// Rotate
unsigned int result = _rotl(value, shift);

// Byte swap
unsigned short swapped = _byteswap_ushort(value);
unsigned long swapped = _byteswap_ulong(value);

// Bit count
int bits = __popcnt(value);

10.4 Cross-Compiler Portable Macros

// Unified attribute macro system
#if defined(__GNUC__) || defined(__clang__)
    #define ATTR_PACKED         __attribute__((packed))
    #define ATTR_ALIGNED(n)     __attribute__((aligned(n)))
    #define ATTR_NORETURN       __attribute__((noreturn))
    #define ATTR_DEPRECATED     __attribute__((deprecated))
    #define ATTR_UNUSED         __attribute__((unused))
    #define ATTR_PURE           __attribute__((pure))
    #define ATTR_CONST          __attribute__((const))
    #define ATTR_FORMAT(x,y,z)  __attribute__((format(x,y,z)))
    #define FORCE_INLINE        __attribute__((always_inline)) inline
    #define THREAD_LOCAL        __thread
#elif defined(_MSC_VER)
    #define ATTR_PACKED         // Use #pragma pack instead
    #define ATTR_ALIGNED(n)     __declspec(align(n))
    #define ATTR_NORETURN       __declspec(noreturn)
    #define ATTR_DEPRECATED     __declspec(deprecated)
    #define ATTR_UNUSED
    #define ATTR_PURE
    #define ATTR_CONST
    #define ATTR_FORMAT(x,y,z)
    #define FORCE_INLINE        __forceinline
    #define THREAD_LOCAL        __declspec(thread)
#else
    #define ATTR_PACKED
    #define ATTR_ALIGNED(n)
    #define ATTR_NORETURN
    #define ATTR_DEPRECATED
    #define ATTR_UNUSED
    #define ATTR_PURE
    #define ATTR_CONST
    #define ATTR_FORMAT(x,y,z)
    #define FORCE_INLINE        inline
    #define THREAD_LOCAL
#endif

// Usage examples
ATTR_NORETURN void panic(const char* msg);

struct ATTR_PACKED {
    char c;
    int i;
} data;

ATTR_ALIGNED(64) char cache_aligned_buffer[1024];

FORCE_INLINE int fast_add(int a, int b) {
    return a + b;
}

THREAD_LOCAL int thread_counter = 0;

Chapter 11: Cross-Platform Compilation

11.1 Platform Detection Header

// platform.h - Unified platform detection
#ifndef PLATFORM_H
#define PLATFORM_H

// Operating System Detection
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
    #define PLATFORM_WINDOWS 1
    #ifdef _WIN64
        #define PLATFORM_WINDOWS_64 1
    #else
        #define PLATFORM_WINDOWS_32 1
    #endif
#elif defined(__linux__)
    #define PLATFORM_LINUX 1
    #define PLATFORM_UNIX 1
#elif defined(__APPLE__) && defined(__MACH__)
    #define PLATFORM_MACOS 1
    #define PLATFORM_UNIX 1
    #include <TargetConditionals.h>
    #if TARGET_OS_IPHONE
        #define PLATFORM_IOS 1
    #endif
#elif defined(__FreeBSD__)
    #define PLATFORM_FREEBSD 1
    #define PLATFORM_BSD 1
    #define PLATFORM_UNIX 1
#elif defined(__OpenBSD__)
    #define PLATFORM_OPENBSD 1
    #define PLATFORM_BSD 1
    #define PLATFORM_UNIX 1
#elif defined(__unix__)
    #define PLATFORM_UNIX 1
#else
    #error "Unsupported platform"
#endif

// Architecture Detection
#if defined(__x86_64__) || defined(_M_X64)
    #define PLATFORM_ARCH_X64 1
    #define PLATFORM_64BIT 1
#elif defined(__i386__) || defined(_M_IX86)
    #define PLATFORM_ARCH_X86 1
    #define PLATFORM_32BIT 1
#elif defined(__aarch64__) || defined(_M_ARM64)
    #define PLATFORM_ARCH_ARM64 1
    #define PLATFORM_64BIT 1
#elif defined(__arm__) || defined(_M_ARM)
    #define PLATFORM_ARCH_ARM 1
    #define PLATFORM_32BIT 1
#elif defined(__powerpc64__)
    #define PLATFORM_ARCH_PPC64 1
    #define PLATFORM_64BIT 1
#elif defined(__powerpc__)
    #define PLATFORM_ARCH_PPC 1
    #define PLATFORM_32BIT 1
#elif defined(__riscv)
    #if __riscv_xlen == 64
        #define PLATFORM_ARCH_RISCV64 1
        #define PLATFORM_64BIT 1
    #else
        #define PLATFORM_ARCH_RISCV32 1
        #define PLATFORM_32BIT 1
    #endif
#else
    #error "Unsupported architecture"
#endif

// Compiler Detection
#if defined(__clang__)
    #define COMPILER_CLANG 1
    #define COMPILER_VERSION_MAJOR __clang_major__
    #define COMPILER_VERSION_MINOR __clang_minor__
#elif defined(__GNUC__)
    #define COMPILER_GCC 1
    #define COMPILER_VERSION_MAJOR __GNUC__
    #define COMPILER_VERSION_MINOR __GNUC_MINOR__
#elif defined(_MSC_VER)
    #define COMPILER_MSVC 1
    #define COMPILER_VERSION_MAJOR (_MSC_VER / 100)
    #define COMPILER_VERSION_MINOR (_MSC_VER % 100)
#elif defined(__INTEL_COMPILER)
    #define COMPILER_INTEL 1
#else
    #define COMPILER_UNKNOWN 1
#endif

// Endianness Detection
#if defined(__BYTE_ORDER__)
    #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
        #define PLATFORM_LITTLE_ENDIAN 1
    #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
        #define PLATFORM_BIG_ENDIAN 1
    #endif
#elif defined(_WIN32)
    #define PLATFORM_LITTLE_ENDIAN 1  // Windows is always little-endian
#else
    // Runtime detection fallback
    static inline int is_little_endian(void) {
        volatile uint32_t i = 0x01234567;
        return (*((uint8_t*)(&i))) == 0x67;
    }
#endif

// Standard types
#include <stdint.h>
#include <stdbool.h>

// Platform-specific includes
#ifdef PLATFORM_WINDOWS
    #ifndef WIN32_LEAN_AND_MEAN
        #define WIN32_LEAN_AND_MEAN
    #endif
    #include <windows.h>
#else
    #include <unistd.h>
    #include <sys/types.h>
#endif

#endif // PLATFORM_H

11.2 Platform-Specific Implementations

// File operations
#ifdef PLATFORM_WINDOWS
    #define PATH_SEPARATOR '\\'
    #define PATH_SEPARATOR_STR "\\"
    #define LINE_ENDING "\r\n"
    
    static inline bool file_exists(const char* path) {
        DWORD attr = GetFileAttributesA(path);
        return attr != INVALID_FILE_ATTRIBUTES;
    }
    
    static inline void sleep_ms(unsigned int ms) {
        Sleep(ms);
    }
    
#else // UNIX-like
    #define PATH_SEPARATOR '/'
    #define PATH_SEPARATOR_STR "/"
    #define LINE_ENDING "\n"
    
    #include <sys/stat.h>
    static inline bool file_exists(const char* path) {
        struct stat st;
        return stat(path, &st) == 0;
    }
    
    static inline void sleep_ms(unsigned int ms) {
        usleep(ms * 1000);
    }
#endif

// Dynamic library loading
#ifdef PLATFORM_WINDOWS
    typedef HMODULE LibHandle;
    #define LOAD_LIBRARY(name) LoadLibraryA(name)
    #define GET_PROC_ADDRESS(lib, name) GetProcAddress(lib, name)
    #define CLOSE_LIBRARY(lib) FreeLibrary(lib)
#else
    #include <dlfcn.h>
    typedef void* LibHandle;
    #define LOAD_LIBRARY(name) dlopen(name, RTLD_LAZY)
    #define GET_PROC_ADDRESS(lib, name) dlsym(lib, name)
    #define CLOSE_LIBRARY(lib) dlclose(lib)
#endif

// Thread creation
#ifdef PLATFORM_WINDOWS
    typedef HANDLE ThreadHandle;
    typedef DWORD (WINAPI *ThreadFunc)(void*);
    
    #define CREATE_THREAD(handle, func, arg) \
        (*(handle) = CreateThread(NULL, 0, func, arg, 0, NULL))
    #define JOIN_THREAD(handle) WaitForSingleObject(handle, INFINITE)
    #define CLOSE_THREAD(handle) CloseHandle(handle)
    
#else
    #include <pthread.h>
    typedef pthread_t ThreadHandle;
    typedef void* (*ThreadFunc)(void*);
    
    #define CREATE_THREAD(handle, func, arg) \
        pthread_create(handle, NULL, func, arg)
    #define JOIN_THREAD(handle) pthread_join(handle, NULL)
    #define CLOSE_THREAD(handle) ((void)0)
#endif

// Atomic operations
#ifdef PLATFORM_WINDOWS
    #include <intrin.h>
    #define ATOMIC_INC(ptr) InterlockedIncrement((volatile LONG*)(ptr))
    #define ATOMIC_DEC(ptr) InterlockedDecrement((volatile LONG*)(ptr))
    #define ATOMIC_ADD(ptr, val) InterlockedAdd((volatile LONG*)(ptr), val)
    
#elif defined(COMPILER_GCC) || defined(COMPILER_CLANG)
    #define ATOMIC_INC(ptr) __sync_add_and_fetch(ptr, 1)
    #define ATOMIC_DEC(ptr) __sync_sub_and_fetch(ptr, 1)
    #define ATOMIC_ADD(ptr, val) __sync_add_and_fetch(ptr, val)
    
#else
    #error "Atomic operations not supported"
#endif

11.3 Build Configuration

// config.h - Build-time configuration
#ifndef CONFIG_H
#define CONFIG_H

// Debug/Release
#if !defined(NDEBUG) || defined(_DEBUG)
    #define BUILD_DEBUG 1
    #define BUILD_RELEASE 0
#else
    #define BUILD_DEBUG 0
    #define BUILD_RELEASE 1
#endif

// Optimization level (GCC/Clang)
#ifdef __OPTIMIZE__
    #define OPTIMIZED 1
#else
    #define OPTIMIZED 0
#endif

// Feature flags
#ifdef ENABLE_LOGGING
    #define LOG(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
#else
    #define LOG(fmt, ...) ((void)0)
#endif

#ifdef ENABLE_PROFILING
    #define PROFILE_START(name) profile_begin(name)
    #define PROFILE_END(name) profile_end(name)
#else
    #define PROFILE_START(name) ((void)0)
    #define PROFILE_END(name) ((void)0)
#endif

// Assertions
#if BUILD_DEBUG
    #define ASSERT(expr) \
        do { \
            if (!(expr)) { \
                fprintf(stderr, "Assertion failed: %s\n", #expr); \
                fprintf(stderr, "  %s:%d in %s\n", __FILE__, __LINE__, __func__); \
                abort(); \
            } \
        } while(0)
#else
    #define ASSERT(expr) ((void)0)
#endif

// Static assertions (C11)
#if __STDC_VERSION__ >= 201112L
    #define STATIC_ASSERT(expr, msg) _Static_assert(expr, msg)
#else
    #define STATIC_ASSERT(expr, msg) \
        typedef char static_assertion_##__LINE__[(expr) ? 1 : -1]
#endif

// Compile-time size checks
STATIC_ASSERT(sizeof(int) == 4, "int must be 32 bits");
STATIC_ASSERT(sizeof(void*) == PLATFORM_64BIT ? 8 : 4, "pointer size mismatch");

#endif // CONFIG_H

Chapter 12: Architecture Detection

12.1 CPU Architecture Macros

// cpu_arch.h - Detailed CPU architecture detection
#ifndef CPU_ARCH_H
#define CPU_ARCH_H

// x86/x64 Detection
#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64)
    #define CPU_X86_64 1
    #define CPU_64BIT 1
    #define CPU_X86_FAMILY 1
#elif defined(__i386__) || defined(_M_IX86) || defined(__i386) || defined(__i486__) || \
      defined(__i586__) || defined(__i686__)
    #define CPU_X86 1
    #define CPU_32BIT 1
    #define CPU_X86_FAMILY 1
#endif

// ARM Detection
#if defined(__aarch64__) || defined(_M_ARM64) || defined(__arm64__)
    #define CPU_ARM64 1
    #define CPU_64BIT 1
    #define CPU_ARM_FAMILY 1
#elif defined(__arm__) || defined(_M_ARM) || defined(__arm)
    #define CPU_ARM 1
    #define CPU_32BIT 1
    #define CPU_ARM_FAMILY 1
    
    // ARM version
    #if defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__)
        #define CPU_ARM_V7 1
    #elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__)
        #define CPU_ARM_V6 1
    #endif
#endif

// PowerPC Detection
#if defined(__powerpc64__) || defined(__ppc64__)
    #define CPU_PPC64 1
    #define CPU_64BIT 1
    #define CPU_PPC_FAMILY 1
#elif defined(__powerpc__) || defined(__ppc__)
    #define CPU_PPC 1
    #define CPU_32BIT 1
    #define CPU_PPC_FAMILY 1
#endif

// MIPS Detection
#if defined(__mips64)
    #define CPU_MIPS64 1
    #define CPU_64BIT 1
    #define CPU_MIPS_FAMILY 1
#elif defined(__mips__)
    #define CPU_MIPS 1
    #define CPU_32BIT 1
    #define CPU_MIPS_FAMILY 1
#endif

// RISC-V Detection
#if defined(__riscv)
    #define CPU_RISCV 1
    #if __riscv_xlen == 64
        #define CPU_RISCV64 1
        #define CPU_64BIT 1
    #elif __riscv_xlen == 32
        #define CPU_RISCV32 1
        #define CPU_32BIT 1
    #endif
#endif

// SPARC Detection
#if defined(__sparc64__)
    #define CPU_SPARC64 1
    #define CPU_64BIT 1
#elif defined(__sparc__)
    #define CPU_SPARC 1
    #define CPU_32BIT 1
#endif

// CPU Features (x86/x64)
#ifdef CPU_X86_FAMILY
    #ifdef __SSE__
        #define CPU_HAS_SSE 1
    #endif
    #ifdef __SSE2__
        #define CPU_HAS_SSE2 1
    #endif
    #ifdef __SSE3__
        #define CPU_HAS_SSE3 1
    #endif
    #ifdef __SSSE3__
        #define CPU_HAS_SSSE3 1
    #endif
    #ifdef __SSE4_1__
        #define CPU_HAS_SSE4_1 1
    #endif
    #ifdef __SSE4_2__
        #define CPU_HAS_SSE4_2 1
    #endif
    #ifdef __AVX__
        #define CPU_HAS_AVX 1
    #endif
    #ifdef __AVX2__
        #define CPU_HAS_AVX2 1
    #endif
    #ifdef __AVX512F__
        #define CPU_HAS_AVX512 1
    #endif
#endif

// ARM Features
#ifdef CPU_ARM_FAMILY
    #ifdef __ARM_NEON
        #define CPU_HAS_NEON 1
    #endif
    #ifdef __ARM_FEATURE_CRC32
        #define CPU_HAS_CRC32 1
    #endif
#endif

// Pointer size
#if defined(CPU_64BIT)
    #define CPU_POINTER_SIZE 8
#else
    #define CPU_POINTER_SIZE 4
#endif

// Cache line size (typical values)
#ifdef CPU_X86_FAMILY
    #define CPU_CACHE_LINE_SIZE 64
#elif defined(CPU_ARM_FAMILY)
    #define CPU_CACHE_LINE_SIZE 64
#elif defined(CPU_PPC_FAMILY)
    #define CPU_CACHE_LINE_SIZE 128
#else
    #define CPU_CACHE_LINE_SIZE 64  // Default
#endif

// Alignment
#define CACHE_ALIGNED __attribute__((aligned(CPU_CACHE_LINE_SIZE)))

#endif // CPU_ARCH_H

12.2 Runtime CPU Feature Detection

// cpu_features.c - Runtime detection (x86/x64)
#ifdef CPU_X86_FAMILY

#include <cpuid.h>

typedef struct {
    bool sse;
    bool sse2;
    bool sse3;
    bool ssse3;
    bool sse4_1;
    bool sse4_2;
    bool avx;
    bool avx2;
    bool avx512f;
    bool fma;
    bool aes;
    bool popcnt;
} CPUFeatures;

static inline void cpuid(int info[4], int function_id, int subfunction_id) {
    __cpuid_count(function_id, subfunction_id, info[0], info[1], info[2], info[3]);
}

CPUFeatures detect_cpu_features(void) {
    CPUFeatures features = {0};
    int info[4];
    
    // Check if CPUID is available
    cpuid(info, 0, 0);
    int max_level = info[0];
    
    if (max_level >= 1) {
        cpuid(info, 1, 0);
        
        // ECX features
        features.sse3   = (info[2] & (1 << 0)) != 0;
        features.ssse3  = (info[2] & (1 << 9)) != 0;
        features.fma    = (info[2] & (1 << 12)) != 0;
        features.sse4_1 = (info[2] & (1 << 19)) != 0;
        features.sse4_2 = (info[2] & (1 << 20)) != 0;
        features.popcnt = (info[2] & (1 << 23)) != 0;
        features.aes    = (info[2] & (1 << 25)) != 0;
        features.avx    = (info[2] & (1 << 28)) != 0;
        
        // EDX features
        features.sse    = (info[3] & (1 << 25)) != 0;
        features.sse2   = (info[3] & (1 << 26)) != 0;
    }
    
    if (max_level >= 7) {
        cpuid(info, 7, 0);
        
        // EBX features
        features.avx2    = (info[1] & (1 << 5)) != 0;
        features.avx512f = (info[1] & (1 << 16)) != 0;
    }
    
    return features;
}

// Usage
void optimized_function(void) {
    static CPUFeatures cpu_features;
    static bool detected = false;
    
    if (!detected) {
        cpu_features = detect_cpu_features();
        detected = true;
    }
    
    if (cpu_features.avx2) {
        // Use AVX2 implementation
    } else if (cpu_features.sse4_2) {
        // Use SSE4.2 implementation
    } else {
        // Use scalar implementation
    }
}

#endif // CPU_X86_FAMILY

Chapter 13: Operating System Detection

13.1 Comprehensive OS Detection

// os_detect.h
#ifndef OS_DETECT_H
#define OS_DETECT_H

// Windows Detection
#if defined(_WIN32) || defined(_WIN64) || defined(__WINDOWS__)
    #define OS_WINDOWS 1
    
    #if defined(_WIN64)
        #define OS_WINDOWS_64 1
    #else
        #define OS_WINDOWS_32 1
    #endif
    
    // Windows version detection
    #ifdef _WIN32_WINNT
        #if _WIN32_WINNT >= 0x0A00
            #define OS_WINDOWS_10 1
        #elif _WIN32_WINNT >= 0x0603
            #define OS_WINDOWS_81 1
        #elif _WIN32_WINNT >= 0x0602
            #define OS_WINDOWS_8 1
        #elif _WIN32_WINNT >= 0x0601
            #define OS_WINDOWS_7 1
        #endif
    #endif
    
    // Windows variant
    #ifdef __CYGWIN__
        #define OS_CYGWIN 1
    #endif
    #ifdef __MINGW32__
        #define OS_MINGW 1
    #endif
    #ifdef __MINGW64__
        #define OS_MINGW64 1
    #endif

// Apple platforms
#elif defined(__APPLE__) && defined(__MACH__)
    #include <TargetConditionals.h>
    #define OS_APPLE 1
    
    #if TARGET_OS_IPHONE
        #define OS_IOS 1
        #if TARGET_OS_SIMULATOR
            #define OS_IOS_SIMULATOR 1
        #endif
    #elif TARGET_OS_MAC
        #define OS_MACOS 1
    #elif TARGET_OS_TV
        #define OS_TVOS 1
    #elif TARGET_OS_WATCH
        #define OS_WATCHOS 1
    #endif

// Linux
#elif defined(__linux__)
    #define OS_LINUX 1
    #define OS_UNIX 1
    
    // Android
    #ifdef __ANDROID__
        #define OS_ANDROID 1
        
        // Android API level
        #ifdef __ANDROID_API__
            #define ANDROID_API_LEVEL __ANDROID_API__
        #endif
    #endif

// BSD variants
#elif defined(__FreeBSD__)
    #define OS_FREEBSD 1
    #define OS_BSD 1
    #define OS_UNIX 1
#elif defined(__OpenBSD__)
    #define OS_OPENBSD 1
    #define OS_BSD 1
    #define OS_UNIX 1
#elif defined(__NetBSD__)
    #define OS_NETBSD 1
    #define OS_BSD 1
    #define OS_UNIX 1
#elif defined(__DragonFly__)
    #define OS_DRAGONFLY 1
    #define OS_BSD 1
    #define OS_UNIX 1

// Solaris
#elif defined(__sun) && defined(__SVR4)
    #define OS_SOLARIS 1
    #define OS_UNIX 1

// Other Unix
#elif defined(__unix__) || defined(__unix)
    #define OS_UNIX 1

// Embedded/RTOS
#elif defined(__VXWORKS__)
    #define OS_VXWORKS 1
#elif defined(__QNX__)
    #define OS_QNX 1

#else
    #error "Unknown operating system"
#endif

// POSIX compliance
#if defined(_POSIX_VERSION)
    #define OS_POSIX 1
    
    #if _POSIX_VERSION >= 200809L
        #define OS_POSIX_2008 1
    #elif _POSIX_VERSION >= 200112L
        #define OS_POSIX_2001 1
    #endif
#endif

// OS families
#if defined(OS_LINUX) || defined(OS_BSD) || defined(OS_MACOS) || defined(OS_UNIX)
    #define OS_UNIX_LIKE 1
#endif

#endif // OS_DETECT_H

13.2 OS-Specific System Calls

// os_api.h - Unified OS API
#ifndef OS_API_H
#define OS_API_H

#include "os_detect.h"
#include <stdint.h>

// File operations
#ifdef OS_WINDOWS
    #include <direct.h>
    #include <io.h>
    #define os_mkdir(path) _mkdir(path)
    #define os_access(path, mode) _access(path, mode)
    #define os_unlink(path) _unlink(path)
    #define os_getcwd(buf, size) _getcwd(buf, size)
#else
    #include <unistd.h>
    #include <sys/stat.h>
    #define os_mkdir(path) mkdir(path, 0755)
    #define os_access(path, mode) access(path, mode)
    #define os_unlink(path) unlink(path)
    #define os_getcwd(buf, size) getcwd(buf, size)
#endif

// Memory mapping
#ifdef OS_WINDOWS
    #include <windows.h>
    typedef struct {
        HANDLE file;
        HANDLE mapping;
        void* addr;
        size_t size;
    } MemoryMap;
    
    static inline MemoryMap* os_mmap(const char* path) {
        MemoryMap* mm = malloc(sizeof(MemoryMap));
        
        mm->file = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ,
                              NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (mm->file == INVALID_HANDLE_VALUE) {
            free(mm);
            return NULL;
        }
        
        LARGE_INTEGER file_size;
        GetFileSizeEx(mm->file, &file_size);
        mm->size = (size_t)file_size.QuadPart;
        
        mm->mapping = CreateFileMappingA(mm->file, NULL, PAGE_READONLY,
                                        0, 0, NULL);
        if (!mm->mapping) {
            CloseHandle(mm->file);
            free(mm);
            return NULL;
        }
        
        mm->addr = MapViewOfFile(mm->mapping, FILE_MAP_READ, 0, 0, 0);
        if (!mm->addr) {
            CloseHandle(mm->mapping);
            CloseHandle(mm->file);
            free(mm);
            return NULL;
        }
        
        return mm;
    }
    
    static inline void os_munmap(MemoryMap* mm) {
        if (mm) {
            if (mm->addr) UnmapViewOfFile(mm->addr);
            if (mm->mapping) CloseHandle(mm->mapping);
            if (mm->file) CloseHandle(mm->file);
            free(mm);
        }
    }
    
#else
    #include <sys/mman.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    
    typedef struct {
        int fd;
        void* addr;
        size_t size;
    } MemoryMap;
    
    static inline MemoryMap* os_mmap(const char* path) {
        MemoryMap* mm = malloc(sizeof(MemoryMap));
        
        mm->fd = open(path, O_RDONLY);
        if (mm->fd < 0) {
            free(mm);
            return NULL;
        }
        
        struct stat st;
        if (fstat(mm->fd, &st) < 0) {
            close(mm->fd);
            free(mm);
            return NULL;
        }
        
        mm->size = st.st_size;
        mm->addr = mmap(NULL, mm->size, PROT_READ, MAP_PRIVATE, mm->fd, 0);
        
        if (mm->addr == MAP_FAILED) {
            close(mm->fd);
            free(mm);
            return NULL;
        }
        
        return mm;
    }
    
    static inline void os_munmap(MemoryMap* mm) {
        if (mm) {
            if (mm->addr) munmap(mm->addr, mm->size);
            if (mm->fd >= 0) close(mm->fd);
            free(mm);
        }
    }
#endif

// High-resolution timer
#ifdef OS_WINDOWS
    static inline uint64_t os_get_time_ns(void) {
        LARGE_INTEGER freq, count;
        QueryPerformanceFrequency(&freq);
        QueryPerformanceCounter(&count);
        return (count.QuadPart * 1000000000ULL) / freq.QuadPart;
    }
#elif defined(OS_MACOS)
    #include <mach/mach_time.h>
    static inline uint64_t os_get_time_ns(void) {
        static mach_timebase_info_data_t timebase;
        if (timebase.denom == 0) {
            mach_timebase_info(&timebase);
        }
        return mach_absolute_time() * timebase.numer / timebase.denom;
    }
#else
    #include <time.h>
    static inline uint64_t os_get_time_ns(void) {
        struct timespec ts;
        clock_gettime(CLOCK_MONOTONIC, &ts);
        return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
    }
#endif

#endif // OS_API_H

Chapter 14: Compiler Detection and Capabilities

14.1 Comprehensive Compiler Detection

// compiler.h
#ifndef COMPILER_H
#define COMPILER_H

// Compiler identification
#if defined(__clang__)
    #define COMPILER_CLANG 1
    #define COMPILER_NAME "Clang"
    #define COMPILER_VERSION \
        (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
    
#elif defined(__INTEL_COMPILER) || defined(__ICC)
    #define COMPILER_INTEL 1
    #define COMPILER_NAME "Intel C++"
    #define COMPILER_VERSION __INTEL_COMPILER
    
#elif defined(__GNUC__)
    #define COMPILER_GCC 1
    #define COMPILER_NAME "GCC"
    #define COMPILER_VERSION \
        (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
    
#elif defined(_MSC_VER)
    #define COMPILER_MSVC 1
    #define COMPILER_NAME "MSVC"
    #define COMPILER_VERSION _MSC_VER
    
#elif defined(__PGI) || defined(__PGIC__)
    #define COMPILER_PGI 1
    #define COMPILER_NAME "PGI"
    
#elif defined(__ARMCC_VERSION)
    #define COMPILER_ARM 1
    #define COMPILER_NAME "ARM"
    #define COMPILER_VERSION __ARMCC_VERSION
    
#elif defined(__TINYC__)
    #define COMPILER_TCC 1
    #define COMPILER_NAME "TinyCC"
    
#else
    #define COMPILER_UNKNOWN 1
    #define COMPILER_NAME "Unknown"
    #define COMPILER_VERSION 0
#endif

// C standard version
#if defined(__STDC_VERSION__)
    #if __STDC_VERSION__ >= 202311L
        #define C_STD_C23 1
        #define C_STD_VERSION 2023
    #elif __STDC_VERSION__ >= 201710L
        #define C_STD_C17 1
        #define C_STD_VERSION 2017
    #elif __STDC_VERSION__ >= 201112L
        #define C_STD_C11 1
        #define C_STD_VERSION 2011
    #elif __STDC_VERSION__ >= 199901L
        #define C_STD_C99 1
        #define C_STD_VERSION 1999
    #else
        #define C_STD_C90 1
        #define C_STD_VERSION 1990
    #endif
#else
    #define C_STD_C89 1
    #define C_STD_VERSION 1989
#endif

// Feature detection macros
#ifdef __has_builtin
    #define HAS_BUILTIN(x) __has_builtin(x)
#else
    #define HAS_BUILTIN(x) 0
#endif

#ifdef __has_feature
    #define HAS_FEATURE(x) __has_feature(x)
#else
    #define HAS_FEATURE(x) 0
#endif

#ifdef __has_attribute
    #define HAS_ATTRIBUTE(x) __has_attribute(x)
#else
    #define HAS_ATTRIBUTE(x) 0
#endif

#ifdef __has_include
    #define HAS_INCLUDE(x) __has_include(x)
#else
    #define HAS_INCLUDE(x) 0
#endif

// Compiler capabilities
#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
    #define HAVE_COMPUTED_GOTO 1
    #define HAVE_STATEMENT_EXPR 1
    #define HAVE_TYPEOF 1
#endif

// Builtin availability
#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
    #define HAVE_BUILTIN_EXPECT 1
    #define HAVE_BUILTIN_CLZ 1
    #define HAVE_BUILTIN_CTZ 1
    #define HAVE_BUILTIN_POPCOUNT 1
    #define HAVE_BUILTIN_BSWAP 1
#endif

#endif // COMPILER_H

14.2 Compiler Version Checks

// Version comparison macros
#define GCC_VERSION_AT_LEAST(major, minor, patch) \
    (defined(COMPILER_GCC) && COMPILER_VERSION >= ((major) * 10000 + (minor) * 100 + (patch)))

#define CLANG_VERSION_AT_LEAST(major, minor, patch) \
    (defined(COMPILER_CLANG) && COMPILER_VERSION >= ((major) * 10000 + (minor) * 100 + (patch)))

#define MSVC_VERSION_AT_LEAST(version) \
    (defined(COMPILER_MSVC) && COMPILER_VERSION >= (version))

// Usage examples
#if GCC_VERSION_AT_LEAST(4, 8, 0)
    // Use GCC 4.8+ features
    #define HAVE_ATOMIC_BUILTINS 1
#endif

#if CLANG_VERSION_AT_LEAST(3, 5, 0)
    // Use Clang 3.5+ features
#endif

#if MSVC_VERSION_AT_LEAST(1900)
    // Use MSVC 2015+ features
    #define HAVE_VARIADIC_TEMPLATES 1
#endif

// C11 features
#if C_STD_VERSION >= 2011
    #define HAVE_STATIC_ASSERT 1
    #define HAVE_GENERIC_SELECTION 1
    #define HAVE_THREAD_LOCAL 1
#endif

14.3 Portable Builtin Wrappers

// builtins.h - Portable compiler builtins
#ifndef BUILTINS_H
#define BUILTINS_H

#include "compiler.h"

// Count leading zeros
#if defined(HAVE_BUILTIN_CLZ)
    #define clz32(x) __builtin_clz(x)
    #define clz64(x) __builtin_clzll(x)
#elif defined(_MSC_VER)
    #include <intrin.h>
    static inline int clz32(uint32_t x) {
        unsigned long index;
        return _BitScanReverse(&index, x) ? 31 - index : 32;
    }
    static inline int clz64(uint64_t x) {
        unsigned long index;
        return _BitScanReverse64(&index, x) ? 63 - index : 64;
    }
#else
    // Fallback implementation
    static inline int clz32(uint32_t x) {
        if (x == 0) return 32;
        int n = 0;
        if (x <= 0x0000FFFF) { n += 16; x <<= 16; }
        if (x <= 0x00FFFFFF) { n += 8;  x <<= 8;  }
        if (x <= 0x0FFFFFFF) { n += 4;  x <<= 4;  }
        if (x <= 0x3FFFFFFF) { n += 2;  x <<= 2;  }
        if (x <= 0x7FFFFFFF) { n += 1; }
        return n;
    }
#endif

// Count trailing zeros
#if defined(HAVE_BUILTIN_CTZ)
    #define ctz32(x) __builtin_ctz(x)
    #define ctz64(x) __builtin_ctzll(x)
#elif defined(_MSC_VER)
    static inline int ctz32(uint32_t x) {
        unsigned long index;
        return _BitScanForward(&index, x) ? index : 32;
    }
    static inline int ctz64(uint64_t x) {
        unsigned long index;
        return _BitScanForward64(&index, x) ? index : 64;
    }
#else
    static inline int ctz32(uint32_t x) {
        if (x == 0) return 32;
        int n = 0;
        if ((x & 0x0000FFFF) == 0) { n += 16; x >>= 16; }
        if ((x & 0x000000FF) == 0) { n += 8;  x >>= 8;  }
        if ((x & 0x0000000F) == 0) { n += 4;  x >>= 4;  }
        if ((x & 0x00000003) == 0) { n += 2;  x >>= 2;  }
        if ((x & 0x00000001) == 0) { n += 1; }
        return n;
    }
#endif

// Population count (count set bits)
#if defined(HAVE_BUILTIN_POPCOUNT)
    #define popcount32(x) __builtin_popcount(x)
    #define popcount64(x) __builtin_popcountll(x)
#elif defined(_MSC_VER)
    #include <intrin.h>
    #define popcount32(x) __popcnt(x)
    #define popcount64(x) __popcnt64(x)
#else
    static inline int popcount32(uint32_t x) {
        x = x - ((x >> 1) & 0x55555555);
        x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
        x = (x + (x >> 4)) & 0x0F0F0F0F;
        x = x + (x >> 8);
        x = x + (x >> 16);
        return x & 0x3F;
    }
#endif

// Byte swap
#if defined(HAVE_BUILTIN_BSWAP)
    #define bswap16(x) __builtin_bswap16(x)
    #define bswap32(x) __builtin_bswap32(x)
    #define bswap64(x) __builtin_bswap64(x)
#elif defined(_MSC_VER)
    #include <stdlib.h>
    #define bswap16(x) _byteswap_ushort(x)
    #define bswap32(x) _byteswap_ulong(x)
    #define bswap64(x) _byteswap_uint64(x)
#else
    static inline uint16_t bswap16(uint16_t x) {
        return (x << 8) | (x >> 8);
    }
    static inline uint32_t bswap32(uint32_t x) {
        return ((x << 24) & 0xFF000000) |
               ((x << 8)  & 0x00FF0000) |
               ((x >> 8)  & 0x0000FF00) |
               ((x >> 24) & 0x000000FF);
    }
#endif

// Prefetch
#if defined(COMPILER_GCC) || defined(COMPILER_CLANG)
    #define PREFETCH_READ(addr)  __builtin_prefetch(addr, 0, 3)
    #define PREFETCH_WRITE(addr) __builtin_prefetch(addr, 1, 3)
#elif defined(_MSC_VER)
    #include <intrin.h>
    #define PREFETCH_READ(addr)  _mm_prefetch((const char*)(addr), _MM_HINT_T0)
    #define PREFETCH_WRITE(addr) _mm_prefetch((const char*)(addr), _MM_HINT_T0)
#else
    #define PREFETCH_READ(addr)  ((void)0)
    #define PREFETCH_WRITE(addr) ((void)0)
#endif

#endif // BUILTINS_H

Chapter 15: Linux Kernel Macro Patterns

15.1 Kernel Coding Style Macros

// Linux kernel-style macros
// From linux/kernel.h

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

// Min/Max (with type checking)
#define min(x, y) ({ \
    typeof(x) _min1 = (x); \
    typeof(y) _min2 = (y); \
    (void) (&_min1 == &_min2); /* Type check */ \
    _min1 < _min2 ? _min1 : _min2; \
})

#define max(x, y) ({ \
    typeof(x) _max1 = (x); \
    typeof(y) _max2 = (y); \
    (void) (&_max1 == &_max2); \
    _max1 > _max2 ? _max1 : _max2; \
})

// Clamp value between min and max
#define clamp(val, lo, hi) min((typeof(val))max(val, lo), hi)

// Swap values
#define swap(a, b) \
    do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0)

// Absolute value
#define abs(x) ({ \
    typeof(x) __x = (x); \
    (__x < 0) ? -__x : __x; \
})

// Round up/down to power of 2
#define roundup_pow_of_two(x) ({ \
    typeof(x) __x = (x); \
    1UL << (sizeof(__x) * 8 - __builtin_clzl(__x - 1)); \
})

#define rounddown_pow_of_two(x) ({ \
    typeof(x) __x = (x); \
    1UL << (sizeof(__x) * 8 - 1 - __builtin_clzl(__x)); \
})

// Alignment macros
#define ALIGN(x, a)      (((x) + (a) - 1) & ~((typeof(x))(a) - 1))
#define ALIGN_DOWN(x, a) ((x) & ~((typeof(x))(a) - 1))
#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0)

// Bit operations
#define BIT(nr)              (1UL << (nr))
#define BIT_MASK(nr)         (1UL << ((nr) % BITS_PER_LONG))
#define BIT_WORD(nr)         ((nr) / BITS_PER_LONG)

// Set, clear, test bits
#define set_bit(nr, addr) \
    ((void)(*(addr) |= BIT_MASK(nr)))

#define clear_bit(nr, addr) \
    ((void)(*(addr) &= ~BIT_MASK(nr)))

#define test_bit(nr, addr) \
    ((*(addr) & BIT_MASK(nr)) != 0)

// Compile-time assertions
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))

// Example usage
BUILD_BUG_ON(sizeof(int) != 4);  // Compile-time check

15.2 Kernel List Macros

// Intrusive linked list (linux/list.h style)

struct list_head {
    struct list_head *next, *prev;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)

static inline void INIT_LIST_HEAD(struct list_head *list) {
    list->next = list;
    list->prev = list;
}

static inline void __list_add(struct list_head *new,
                             struct list_head *prev,
                             struct list_head *next) {
    next->prev = new;
    new->next = next;
    new->prev = prev;
    prev->next = new;
}

static inline void list_add(struct list_head *new, struct list_head *head) {
    __list_add(new, head, head->next);
}

static inline void list_add_tail(struct list_head *new, struct list_head *head) {
    __list_add(new, head->prev, head);
}

// List iteration
#define list_entry(ptr, type, member) \
    container_of(ptr, type, member)

#define list_first_entry(ptr, type, member) \
    list_entry((ptr)->next, type, member)

#define list_next_entry(pos, member) \
    list_entry((pos)->member.next, typeof(*(pos)), member)

#define list_for_each(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next)

#define list_for_each_entry(pos, head, member) \
    for (pos = list_first_entry(head, typeof(*pos), member); \
         &pos->member != (head); \
         pos = list_next_entry(pos, member))

// Safe iteration (allows removal)
#define list_for_each_safe(pos, n, head) \
    for (pos = (head)->next, n = pos->next; pos != (head); \
         pos = n, n = pos->next)

#define list_for_each_entry_safe(pos, n, head, member) \
    for (pos = list_first_entry(head, typeof(*pos), member), \
         n = list_next_entry(pos, member); \
         &pos->member != (head); \
         pos = n, n = list_next_entry(n, member))

// Example usage
struct my_struct {
    int data;
    struct list_head list;
};

LIST_HEAD(my_list);

void example(void) {
    struct my_struct *item, *tmp;
    
    // Add items
    struct my_struct *new_item = malloc(sizeof(*new_item));
    new_item->data = 42;
    list_add(&new_item->list, &my_list);
    
    // Iterate
    list_for_each_entry(item, &my_list, list) {
        printf("Data: %d\n", item->data);
    }
    
    // Safe iteration with removal
    list_for_each_entry_safe(item, tmp, &my_list, list) {
        if (item->data == 42) {
            list_del(&item->list);
            free(item);
        }
    }
}

15.3 Kernel Hash Table Macros

// Hash list (linux/hashtable.h style)

#define HASH_SIZE(bits) (1UL << (bits))
#define HASH_MASK(bits) (HASH_SIZE(bits) - 1)

#define DECLARE_HASHTABLE(name, bits) \
    struct hlist_head name[HASH_SIZE(bits)]

#define HASH_BITS_DEFAULT 8

struct hlist_head {
    struct hlist_node *first;
};

struct hlist_node {
    struct hlist_node *next, **pprev;
};

#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)

static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) {
    struct hlist_node *first = h->first;
    n->next = first;
    if (first)
        first->pprev = &n->next;
    h->first = n;
    n->pprev = &h->first;
}

// Hash table iteration
#define hash_for_each(name, bkt, node, member) \
    for ((bkt) = 0; (bkt) < HASH_SIZE(ARRAY_SIZE(name)); (bkt)++) \
        hlist_for_each_entry(node, &name[bkt], member)

#define hlist_for_each_entry(pos, head, member) \
    for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member); \
         pos; \
         pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))

// Example
struct my_hash_entry {
    int key;
    int value;
    struct hlist_node node;
};

DECLARE_HASHTABLE(my_htable, 8);

static inline unsigned int hash_int(int key) {
    return key * 2654435761U;  // Knuth's multiplicative hash
}

void hash_table_example(void) {
    int bkt;
    struct my_hash_entry *entry;
    
    // Initialize
    for (bkt = 0; bkt < HASH_SIZE(8); bkt++) {
        INIT_HLIST_HEAD(&my_htable[bkt]);
    }
    
    // Insert
    struct my_hash_entry *new_entry = malloc(sizeof(*new_entry));
    new_entry->key = 42;
    new_entry->value = 100;
    
    unsigned int hash = hash_int(new_entry->key) & HASH_MASK(8);
    hlist_add_head(&new_entry->node, &my_htable[hash]);
    
    // Lookup
    hash = hash_int(42) & HASH_MASK(8);
    hlist_for_each_entry(entry, &my_htable[hash], node) {
        if (entry->key == 42) {
            printf("Found: value = %d\n", entry->value);
            break;
        }
    }
}

Chapter 16: Container_of and Type-Safe Macros

16.1 The container_of Macro

// The famous Linux kernel container_of macro
// From linux/kernel.h

/**
 * container_of - cast a member of a structure out to the containing structure
 * @ptr:    the pointer to the member.
 * @type:   the type of the container struct this is embedded in.
 * @member: the name of the member within the struct.
 */
#define container_of(ptr, type, member) ({ \
    const typeof(((type *)0)->member) *__mptr = (ptr); \
    (type *)((char *)__mptr - offsetof(type, member)); \
})

// Example: Getting parent struct from embedded member

struct person {
    char name[32];
    int age;
    struct list_head friends;  // Embedded list node
};

void process_friend(struct list_head *friend_node) {
    // Get the person struct containing this list node
    struct person *p = container_of(friend_node, struct person, friends);
    
    printf("Name: %s, Age: %d\n", p->name, p->age);
}

// How it works:
// 1. typeof(((type *)0)->member) - Get type of the member
// 2. const typeof(...) *__mptr = (ptr) - Type-safe pointer assignment
// 3. offsetof(type, member) - Get byte offset of member in struct
// 4. (char *)__mptr - offsetof(...) - Subtract offset to get struct start
// 5. (type *) - Cast back to original struct type

16.2 Understanding container_of in Detail

// Step-by-step explanation
#include <stddef.h>  // for offsetof

struct example {
    int a;
    int b;
    int c;
};

void demo_container_of(void) {
    struct example ex = {1, 2, 3};
    int *b_ptr = &ex.b;
    
    // Manual calculation:
    // 1. Get offset of 'b' in struct example
    size_t offset = offsetof(struct example, b);  // = 4 bytes (on 32-bit)
    
    // 2. Subtract offset from member pointer to get struct pointer
    struct example *ex_ptr = (struct example *)((char *)b_ptr - offset);
    
    // Using container_of:
    struct example *ex_ptr2 = container_of(b_ptr, struct example, b);
    
    // Both point to the same struct
    assert(ex_ptr == ex_ptr2);
    assert(ex_ptr == &ex);
}

// Type safety
void demonstrate_type_safety(void) {
    struct example ex = {1, 2, 3};
    float *wrong_ptr = (float *)&ex.b;
    
    // This will give a compiler warning due to type checking!
    // struct example *ex_ptr = container_of(wrong_ptr, struct example, b);
    
    // The typeof check catches this:
    // const typeof(((struct example *)0)->b) *__mptr = wrong_ptr;
    // __mptr expects int*, but wrong_ptr is float*
}

16.3 Practical container_of Examples

// File descriptor abstraction
struct file_ops {
    int (*read)(void *ctx, void *buf, size_t count);
    int (*write)(void *ctx, const void *buf, size_t count);
    void (*close)(void *ctx);
};

struct file {
    struct file_ops *ops;
    void *private_data;
};

// Network socket implementation
struct socket {
    struct file file;  // Embedded file struct
    int sock_fd;
    char addr[64];
};

int socket_read(void *ctx, void *buf, size_t count) {
    // Get socket from embedded file struct
    struct socket *sock = container_of(ctx, struct socket, file);
    return recv(sock->sock_fd, buf, count, 0);
}

struct file_ops socket_ops = {
    .read = socket_read,
    // ...
};

// Timer implementation
struct timer_list {
    struct list_head entry;
    unsigned long expires;
    void (*function)(struct timer_list *);
    unsigned long data;
};

struct my_timer_data {
    int id;
    struct timer_list timer;
    char info[64];
};

void my_timer_callback(struct timer_list *timer) {
    // Get our data structure from embedded timer
    struct my_timer_data *data = 
        container_of(timer, struct my_timer_data, timer);
    
    printf("Timer %d expired: %s\n", data->id, data->info);
}

16.4 Type-Safe Generic Containers

// Using container_of for type-safe generic data structures

// Generic queue implemented with container_of
struct queue_node {
    struct queue_node *next;
};

struct queue {
    struct queue_node *head;
    struct queue_node *tail;
};

#define INIT_QUEUE(q) do { \
    (q)->head = NULL; \
    (q)->tail = NULL; \
} while (0)

#define queue_push(q, node) do { \
    (node)->next = NULL; \
    if ((q)->tail) \
        (q)->tail->next = (node); \
    else \
        (q)->head = (node); \
    (q)->tail = (node); \
} while (0)

#define queue_pop(q) ({ \
    struct queue_node *__node = (q)->head; \
    if (__node) { \
        (q)->head = __node->next; \
        if (!(q)->head) \
            (q)->tail = NULL; \
    } \
    __node; \
})

// Type-safe wrapper
#define DEFINE_QUEUE_TYPE(type, member) \
    static inline void type##_queue_push(struct queue *q, type *item) { \
        queue_push(q, &item->member); \
    } \
    static inline type *type##_queue_pop(struct queue *q) { \
        struct queue_node *node = queue_pop(q); \
        return node ? container_of(node, type, member) : NULL; \
    }

// Usage
struct packet {
    int id;
    char data[1024];
    struct queue_node qnode;
};

DEFINE_QUEUE_TYPE(packet, qnode)

void example_queue(void) {
    struct queue q;
    INIT_QUEUE(&q);
    
    struct packet *p = malloc(sizeof(*p));
    p->id = 42;
    
    packet_queue_push(&q, p);
    
    struct packet *retrieved = packet_queue_pop(&q);
    printf("Packet ID: %d\n", retrieved->id);
}

Chapter 17: Likely/Unlikely Branch Hints

17.1 Understanding Branch Prediction

// Branch prediction helps CPUs execute code faster
// Mispredicted branches can cost 10-20 cycles

// Linux kernel likely/unlikely macros
// From linux/compiler.h

#if defined(__GNUC__) || defined(__clang__)
    #define likely(x)   __builtin_expect(!!(x), 1)
    #define unlikely(x) __builtin_expect(!!(x), 0)
#else
    #define likely(x)   (x)
    #define unlikely(x) (x)
#endif

// How it works:
// __builtin_expect(expr, expected_value)
// Tells compiler: "expr will usually equal expected_value"
// Compiler generates code with better branch layout

// Examples from real code:

// Error path (rarely taken)
if (unlikely(ptr == NULL)) {
    return -ENOMEM;  // Cold path
}
// Hot path continues here

// Success path (usually taken)
if (likely(count > 0)) {
    process_data(buffer, count);  // Hot path
}

// Loop condition (usually true until end)
while (likely(i < len)) {
    sum += array[i++];
}

17.2 Proper Usage Patterns

// GOOD: Error checking
int allocate_buffer(void **buf, size_t size) {
    *buf = malloc(size);
    if (unlikely(*buf == NULL)) {
        log_error("Out of memory");
        return -ENOMEM;
    }
    return 0;
}

// GOOD: Rare event
void critical_section(void) {
    if (unlikely(need_debug_trace)) {
        log_debug_trace();
    }
    // Main code path
}

// GOOD: Frequently true condition
void process_list(struct list_head *list) {
    struct entry *item;
    
    list_for_each_entry(item, list, node) {
        if (likely(item->valid)) {
            process(item);
        }
    }
}

// BAD: Balanced branch (50/50)
if (unlikely(x % 2 == 0)) {  // Don't use unlikely here!
    // Even
} else {
    // Odd
}

// BAD: Input-dependent
if (unlikely(user_input > 0)) {  // Unknown distribution!
    // ...
}

// GOOD: Known hot path
int fast_lookup(int key) {
    int result = cache_get(key);
    if (likely(result != -1)) {
        return result;  // Cache hit (hot path)
    }
    
    // Cache miss (cold path)
    return slow_lookup(key);
}

17.3 Performance Impact Examples

// Example: Kernel spinlock (simplified)

typedef struct {
    volatile int locked;
} spinlock_t;

void spin_lock(spinlock_t *lock) {
    while (1) {
        // Try to acquire
        if (likely(!lock->locked)) {  // Usually unlocked
            if (__sync_bool_compare_and_swap(&lock->locked, 0, 1)) {
                return;  // Got it
            }
        }
        
        // Spin - this is the slow path
        while (unlikely(lock->locked)) {
            cpu_relax();  // Hint to CPU
        }
    }
}

void spin_unlock(spinlock_t *lock) {
    // Release
    __sync_synchronize();
    lock->locked = 0;
}

// Example: Fast path optimization
struct cache_entry {
    int key;
    int value;
    bool valid;
};

#define CACHE_SIZE 64
struct cache_entry cache[CACHE_SIZE];

int cached_compute(int key) {
    int hash = key & (CACHE_SIZE - 1);
    
    // Fast path: cache hit
    if (likely(cache[hash].valid && cache[hash].key == key)) {
        return cache[hash].value;  // ~1 cycle
    }
    
    // Slow path: cache miss
    int value = expensive_computation(key);  // ~1000 cycles
    
    // Update cache
    cache[hash].key = key;
    cache[hash].value = value;
    cache[hash].valid = true;
    
    return value;
}

// Example: Error checking in hot loop
void process_packets(struct packet *packets, int count) {
    for (int i = 0; i < count; i++) {
        // Validate packet (rarely fails)
        if (unlikely(!validate_packet(&packets[i]))) {
            drop_packet(&packets[i]);
            continue;
        }
        
        // Process packet (hot path)
        if (likely(packets[i].type == TYPE_DATA)) {
            process_data_packet(&packets[i]);
        } else {
            process_control_packet(&packets[i]);
        }
    }
}

17.4 Assembly Output Comparison

// Source code
int check_value(int x) {
    if (unlikely(x < 0)) {
        return handle_error();
    }
    return x * 2;
}

// Without unlikely - Assembly (simplified):
//   test    %edi, %edi
//   jl      .L_error      ; Branch to error
//   lea     (%rdi,%rdi), %eax
//   ret
// .L_error:
//   jmp     handle_error

// With unlikely - Assembly (simplified):
//   test    %edi, %edi
//   jge     .L_success    ; Branch to success (fall-through to error)
//   jmp     handle_error
// .L_success:
//   lea     (%rdi,%rdi), %eax
//   ret

// Notice: Hot path has better code layout (no jump in common case)

Chapter 18: Barrier and Atomic Operations

18.1 Memory Barriers

// Memory barriers prevent compiler and CPU reordering
// Critical for lock-free data structures and kernel code

// Compiler barriers
#if defined(__GNUC__) || defined(__clang__)
    #define barrier() __asm__ __volatile__("" ::: "memory")
#elif defined(_MSC_VER)
    #define barrier() _ReadWriteBarrier()
#else
    #define barrier() do { } while (0)
#endif

// Full memory barrier (compiler + CPU)
#if defined(__GNUC__) || defined(__clang__)
    #define mb()  __sync_synchronize()
    #define rmb() __asm__ __volatile__("" ::: "memory")  // Read barrier
    #define wmb() __asm__ __volatile__("" ::: "memory")  // Write barrier
#elif defined(_MSC_VER)
    #include <intrin.h>
    #define mb()  _mm_mfence()
    #define rmb() _mm_lfence()
    #define wmb() _mm_sfence()
#endif

// Architecture-specific barriers (Linux kernel style)
#ifdef CPU_X86_FAMILY
    // x86/x64 has strong memory model
    #define smp_mb()  __asm__ __volatile__("mfence" ::: "memory")
    #define smp_rmb() __asm__ __volatile__("lfence" ::: "memory")
    #define smp_wmb() __asm__ __volatile__("sfence" ::: "memory")
#elif defined(CPU_ARM_FAMILY)
    // ARM requires explicit barriers
    #define smp_mb()  __asm__ __volatile__("dmb" ::: "memory")
    #define smp_rmb() __asm__ __volatile__("dmb" ::: "memory")
    #define smp_wmb() __asm__ __volatile__("dmb st" ::: "memory")
#else
    #define smp_mb()  mb()
    #define smp_rmb() rmb()
    #define smp_wmb() wmb()
#endif

// CPU relax (for spinlocks)
#ifdef CPU_X86_FAMILY
    #define cpu_relax() __asm__ __volatile__("pause" ::: "memory")
#elif defined(CPU_ARM_FAMILY)
    #define cpu_relax() __asm__ __volatile__("yield" ::: "memory")
#else
    #define cpu_relax() barrier()
#endif

18.2 Atomic Operations

// Portable atomic operations

// GCC/Clang atomic builtins
#if defined(__GNUC__) || defined(__clang__)

    #define atomic_read(v)  __atomic_load_n(v, __ATOMIC_SEQ_CST)
    #define atomic_set(v, i) __atomic_store_n(v, i, __ATOMIC_SEQ_CST)
    
    #define atomic_add(v, i) __atomic_add_fetch(v, i, __ATOMIC_SEQ_CST)
    #define atomic_sub(v, i) __atomic_sub_fetch(v, i, __ATOMIC_SEQ_CST)
    #define atomic_inc(v)    __atomic_add_fetch(v, 1, __ATOMIC_SEQ_CST)
    #define atomic_dec(v)    __atomic_sub_fetch(v, 1, __ATOMIC_SEQ_CST)
    
    #define atomic_and(v, i) __atomic_and_fetch(v, i, __ATOMIC_SEQ_CST)
    #define atomic_or(v, i)  __atomic_or_fetch(v, i, __ATOMIC_SEQ_CST)
    #define atomic_xor(v, i) __atomic_xor_fetch(v, i, __ATOMIC_SEQ_CST)
    
    #define atomic_cmpxchg(v, old, new) \
        __sync_val_compare_and_swap(v, old, new)
    
    #define atomic_xchg(v, new) \
        __atomic_exchange_n(v, new, __ATOMIC_SEQ_CST)

// MSVC intrinsics
#elif defined(_MSC_VER)

    #include <intrin.h>
    
    #define atomic_read(v)  (*(volatile int*)(v))
    #define atomic_set(v, i) (*(volatile int*)(v) = (i))
    
    #define atomic_add(v, i) _InterlockedExchangeAdd((volatile long*)(v), i)
    #define atomic_sub(v, i) _InterlockedExchangeAdd((volatile long*)(v), -(i))
    #define atomic_inc(v)    _InterlockedIncrement((volatile long*)(v))
    #define atomic_dec(v)    _InterlockedDecrement((volatile long*)(v))
    
    #define atomic_cmpxchg(v, old, new) \
        _InterlockedCompareExchange((volatile long*)(v), new, old)
    
    #define atomic_xchg(v, new) \
        _InterlockedExchange((volatile long*)(v), new)

#endif

// Atomic types
typedef struct {
    volatile int counter;
} atomic_t;

typedef struct {
    volatile long counter;
} atomic_long_t;

#define ATOMIC_INIT(i) { (i) }

// Atomic operations with relaxed ordering (faster)
#define atomic_read_relaxed(v) \
    __atomic_load_n(&(v)->counter, __ATOMIC_RELAXED)

#define atomic_set_relaxed(v, i) \
    __atomic_store_n(&(v)->counter, i, __ATOMIC_RELAXED)

18.3 Lock-Free Data Structures

// Example: Lock-free stack

struct lf_stack_node {
    struct lf_stack_node *next;
    void *data;
};

struct lf_stack {
    struct lf_stack_node *head;
};

void lf_stack_init(struct lf_stack *stack) {
    atomic_set((atomic_t *)&stack->head, (int)NULL);
}

void lf_stack_push(struct lf_stack *stack, struct lf_stack_node *node) {
    struct lf_stack_node *old_head;
    
    do {
        old_head = (struct lf_stack_node *)atomic_read((atomic_t *)&stack->head);
        node->next = old_head;
        
        // Try to update head atomically
    } while (atomic_cmpxchg((atomic_t *)&stack->head, 
                           (int)old_head, (int)node) != (int)old_head);
}

struct lf_stack_node *lf_stack_pop(struct lf_stack *stack) {
    struct lf_stack_node *head, *next;
    
    do {
        head = (struct lf_stack_node *)atomic_read((atomic_t *)&stack->head);
        
        if (unlikely(head == NULL)) {
            return NULL;
        }
        
        next = head->next;
        
        // Try to update head atomically
    } while (atomic_cmpxchg((atomic_t *)&stack->head,
                           (int)head, (int)next) != (int)head);
    
    return head;
}

// Example: Spinlock implementation
typedef struct {
    atomic_t locked;
} spinlock_t;

#define SPINLOCK_INIT { ATOMIC_INIT(0) }

void spin_lock(spinlock_t *lock) {
    while (1) {
        // Fast path: try to acquire
        if (likely(!atomic_read(&lock->locked))) {
            if (atomic_cmpxchg(&lock->locked, 0, 1) == 0) {
                // Acquired!
                smp_mb();  // Memory barrier
                return;
            }
        }
        
        // Slow path: spin
        while (unlikely(atomic_read(&lock->locked))) {
            cpu_relax();  // Be nice to other cores
        }
    }
}

void spin_unlock(spinlock_t *lock) {
    smp_mb();  // Ensure all writes complete
    atomic_set(&lock->locked, 0);
}

// Example: Reference counting
struct refcounted {
    atomic_t refcount;
    void (*release)(struct refcounted *);
};

void refcount_init(struct refcounted *obj) {
    atomic_set(&obj->refcount, 1);
}

void refcount_get(struct refcounted *obj) {
    int old = atomic_inc(&obj->refcount);
    
    // Check for overflow
    if (unlikely(old <= 0)) {
        atomic_dec(&obj->refcount);
        // Handle error
    }
}

void refcount_put(struct refcounted *obj) {
    if (atomic_dec(&obj->refcount) == 0) {
        // Last reference - cleanup
        smp_mb();
        if (obj->release) {
            obj->release(obj);
        }
    }
}

Chapter 19: Debugging and Assertion Macros

19.1 Debug Logging System

// debug.h - Comprehensive debug logging

// Debug levels
typedef enum {
    DEBUG_NONE  = 0,
    DEBUG_ERROR = 1,
    DEBUG_WARN  = 2,
    DEBUG_INFO  = 3,
    DEBUG_DEBUG = 4,
    DEBUG_TRACE = 5
} debug_level_t;

#ifndef DEBUG_LEVEL
    #define DEBUG_LEVEL DEBUG_INFO
#endif

// Color codes for terminal
#ifdef USE_COLORS
    #define COLOR_RED     "\033[31m"
    #define COLOR_YELLOW  "\033[33m"
    #define COLOR_GREEN   "\033[32m"
    #define COLOR_CYAN    "\033[36m"
    #define COLOR_RESET   "\033[0m"
#else
    #define COLOR_RED     ""
    #define COLOR_YELLOW  ""
    #define COLOR_GREEN   ""
    #define COLOR_CYAN    ""
    #define COLOR_RESET   ""
#endif

// Debug print macro
#define DEBUG_PRINT(level, color, tag, fmt, ...) \
    do { \
        if (DEBUG_LEVEL >= (level)) { \
            fprintf(stderr, "%s[%s] %s:%d in %s(): " fmt "%s\n", \
                   color, tag, __FILE__, __LINE__, __func__, \
                   ##__VA_ARGS__, COLOR_RESET); \
        } \
    } while (0)

// Logging macros
#define ERROR(fmt, ...) \
    DEBUG_PRINT(DEBUG_ERROR, COLOR_RED, "ERROR", fmt, ##__VA_ARGS__)

#define WARN(fmt, ...) \
    DEBUG_PRINT(DEBUG_WARN, COLOR_YELLOW, "WARN", fmt, ##__VA_ARGS__)

#define INFO(fmt, ...) \
    DEBUG_PRINT(DEBUG_INFO, COLOR_GREEN, "INFO", fmt, ##__VA_ARGS__)

#define DEBUG(fmt, ...) \
    DEBUG_PRINT(DEBUG_DEBUG, COLOR_CYAN, "DEBUG", fmt, ##__VA_ARGS__)

#define TRACE(fmt, ...) \
    DEBUG_PRINT(DEBUG_TRACE, COLOR_RESET, "TRACE", fmt, ##__VA_ARGS__)

// Usage
void example_function(int x) {
    TRACE("Entering with x=%d", x);
    
    if (unlikely(x < 0)) {
        ERROR("Invalid value: x=%d", x);
        return;
    }
    
    DEBUG("Processing x=%d", x);
    INFO("Operation completed successfully");
}

19.2 Assertion Macros

// assertions.h - Compile-time and runtime assertions

// Runtime assertion (debug builds only)
#ifndef NDEBUG
    #define ASSERT(expr) \
        do { \
            if (unlikely(!(expr))) { \
                fprintf(stderr, \
                    COLOR_RED "Assertion failed: %s" COLOR_RESET "\n" \
                    "  File: %s:%d\n" \
                    "  Function: %s\n", \
                    #expr, __FILE__, __LINE__, __func__); \
                abort(); \
            } \
        } while (0)
    
    #define ASSERT_MSG(expr, fmt, ...) \
        do { \
            if (unlikely(!(expr))) { \
                fprintf(stderr, \
                    COLOR_RED "Assertion failed: %s" COLOR_RESET "\n" \
                    "  File: %s:%d\n" \
                    "  Function: %s\n" \
                    "  Message: " fmt "\n", \
                    #expr, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \
                abort(); \
            } \
        } while (0)
#else
    #define ASSERT(expr)               ((void)0)
    #define ASSERT_MSG(expr, fmt, ...) ((void)0)
#endif

// Compile-time assertion (all builds)
#if __STDC_VERSION__ >= 201112L
    #define STATIC_ASSERT(expr, msg) _Static_assert(expr, msg)
#else
    #define STATIC_ASSERT(expr, msg) \
        typedef char static_assertion_##__LINE__[(expr) ? 1 : -1]
#endif

// Verify (always checked, even in release)
#define VERIFY(expr) \
    do { \
        if (unlikely(!(expr))) { \
            fprintf(stderr, \
                COLOR_RED "Verification failed: %s" COLOR_RESET "\n" \
                "  File: %s:%d\n" \
                "  Function: %s\n", \
                #expr, __FILE__, __LINE__, __func__); \
            abort(); \
        } \
    } while (0)

// Bounds checking
#define ASSERT_BOUNDS(index, size) \
    ASSERT_MSG((index) >= 0 && (index) < (size), \
               "Index %d out of bounds [0, %d)", (int)(index), (int)(size))

// Pointer checking
#define ASSERT_NOT_NULL(ptr) \
    ASSERT_MSG((ptr) != NULL, "Unexpected NULL pointer: %s", #ptr)

// Type checking
#define ASSERT_TYPE_SIZE(type, size) \
    STATIC_ASSERT(sizeof(type) == (size), \
                  "Size mismatch: " #type " should be " #size " bytes")

// Examples
void example_assertions(void) {
    // Compile-time checks
    STATIC_ASSERT(sizeof(int) == 4, "int must be 32 bits");
    ASSERT_TYPE_SIZE(void*, 8);  // On 64-bit systems
    
    // Runtime checks
    int *ptr = malloc(sizeof(int));
    ASSERT_NOT_NULL(ptr);
    
    int array[10];
    int index = get_index();
    ASSERT_BOUNDS(index, 10);
    array[index] = 42;
    
    // Condition with message
    int value = calculate_value();
    ASSERT_MSG(value >= 0 && value <= 100,
               "Value %d out of valid range [0, 100]", value);
}

19.3 Advanced Debugging Macros

// debug_advanced.h

// Dump variable values
#define DUMP_VAR(var) \
    printf("%s:%d: %s = ", __FILE__, __LINE__, #var); \
    _Generic((var), \
        char:               printf("%c\n", var), \
        int:                printf("%d\n", var), \
        long:               printf("%ld\n", var), \
        unsigned:           printf("%u\n", var), \
        unsigned long:      printf("%lu\n", var), \
        float:              printf("%f\n", var), \
        double:             printf("%f\n", var), \
        char*:              printf("%s\n", var), \
        const char*:        printf("%s\n", var), \
        void*:              printf("%p\n", var), \
        default:            printf("<%s>\n", "unknown type") \
    )

// Function entry/exit tracing
#define TRACE_FUNC() \
    do { \
        static int __call_count = 0; \
        printf("[TRACE] %s() called (%d times)\n", __func__, ++__call_count); \
    } while (0)

// Performance timing
#define TIME_BLOCK_BEGIN(name) \
    do { \
        static uint64_t __start_##name; \
        __start_##name = get_timestamp_ns();

#define TIME_BLOCK_END(name) \
        uint64_t __duration_##name = get_timestamp_ns() - __start_##name; \
        printf("[TIME] %s: %llu ns\n", #name, \
               (unsigned long long)__duration_##name); \
    } while (0)

// Memory allocation tracking
#ifndef NDEBUG
    #define DEBUG_MALLOC(size) ({ \
        void *__ptr = malloc(size); \
        printf("[ALLOC] %p: %zu bytes at %s:%d\n", \
               __ptr, (size_t)(size), __FILE__, __LINE__); \
        __ptr; \
    })
    
    #define DEBUG_FREE(ptr) \
        do { \
            printf("[FREE] %p at %s:%d\n", ptr, __FILE__, __LINE__); \
            free(ptr); \
        } while (0)
#else
    #define DEBUG_MALLOC(size) malloc(size)
    #define DEBUG_FREE(ptr)    free(ptr)
#endif

// Usage examples
void debugging_examples(void) {
    TRACE_FUNC();
    
    int x = 42;
    DUMP_VAR(x);
    
    char *str = "Hello";
    DUMP_VAR(str);
    
    TIME_BLOCK_BEGIN(calculation);
    // Expensive operation
    for (int i = 0; i < 1000000; i++) {
        volatile int dummy = i * i;
        (void)dummy;
    }
    TIME_BLOCK_END(calculation);
    
    int *ptr = DEBUG_MALLOC(sizeof(int) * 100);
    DEBUG_FREE(ptr);
}

Chapter 20: Complete Cross-Platform Project

20.1 Project Structure

cross_platform_app/
├── include/
│   ├── platform.h      # Platform detection
│   ├── compiler.h      # Compiler detection
│   ├── types.h         # Portable types
│   ├── atomic.h        # Atomic operations
│   ├── debug.h         # Debug macros
│   └── app.h           # Application API
├── src/
│   ├── main.c
│   ├── platform_unix.c
│   ├── platform_win.c
│   └── app.c
├── Makefile
├── Makefile.gcc
├── Makefile.msvc
└── README.md

20.2 Complete Implementation

// platform.h - Master platform header
#ifndef PLATFORM_H
#define PLATFORM_H

// Include all platform detection
#include "compiler.h"

// OS Detection
#if defined(_WIN32)
    #define PLATFORM_WINDOWS 1
    #define PLATFORM_NAME "Windows"
#elif defined(__linux__)
    #define PLATFORM_LINUX 1
    #define PLATFORM_NAME "Linux"
#elif defined(__APPLE__)
    #define PLATFORM_MACOS 1
    #define PLATFORM_NAME "macOS"
#else
    #error "Unsupported platform"
#endif

// Architecture
#if defined(__x86_64__) || defined(_M_X64)
    #define PLATFORM_X64 1
    #define PLATFORM_BITS 64
#else
    #define PLATFORM_X86 1
    #define PLATFORM_BITS 32
#endif

// Portable types
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

// Platform-specific includes
#ifdef PLATFORM_WINDOWS
    #include <windows.h>
    typedef HANDLE thread_t;
    typedef CRITICAL_SECTION mutex_t;
#else
    #include <pthread.h>
    #include <unistd.h>
    typedef pthread_t thread_t;
    typedef pthread_mutex_t mutex_t;
#endif

// Portable API
void platform_init(void);
void platform_cleanup(void);
void platform_sleep_ms(unsigned int ms);
uint64_t platform_get_time_ns(void);

int thread_create(thread_t *thread, void *(*func)(void*), void *arg);
int thread_join(thread_t thread);

void mutex_init(mutex_t *mutex);
void mutex_lock(mutex_t *mutex);
void mutex_unlock(mutex_t *mutex);
void mutex_destroy(mutex_t *mutex);

#endif // PLATFORM_H
// platform_unix.c - Unix implementation
#if defined(PLATFORM_LINUX) || defined(PLATFORM_MACOS)

#include "platform.h"
#include <time.h>
#include <unistd.h>

void platform_init(void) {
    // Unix-specific initialization
}

void platform_cleanup(void) {
    // Cleanup
}

void platform_sleep_ms(unsigned int ms) {
    usleep(ms * 1000);
}

uint64_t platform_get_time_ns(void) {
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
}

int thread_create(thread_t *thread, void *(*func)(void*), void *arg) {
    return pthread_create(thread, NULL, func, arg);
}

int thread_join(thread_t thread) {
    return pthread_join(thread, NULL);
}

void mutex_init(mutex_t *mutex) {
    pthread_mutex_init(mutex, NULL);
}

void mutex_lock(mutex_t *mutex) {
    pthread_mutex_lock(mutex);
}

void mutex_unlock(mutex_t *mutex) {
    pthread_mutex_unlock(mutex);
}

void mutex_destroy(mutex_t *mutex) {
    pthread_mutex_destroy(mutex);
}

#endif // Unix platforms
// platform_win.c - Windows implementation
#ifdef PLATFORM_WINDOWS

#include "platform.h"

void platform_init(void) {
    // Windows-specific initialization
}

void platform_cleanup(void) {
    // Cleanup
}

void platform_sleep_ms(unsigned int ms) {
    Sleep(ms);
}

uint64_t platform_get_time_ns(void) {
    LARGE_INTEGER freq, count;
    QueryPerformanceFrequency(&freq);
    QueryPerformanceCounter(&count);
    return (count.QuadPart * 1000000000ULL) / freq.QuadPart;
}

typedef struct {
    HANDLE handle;
    void *(*func)(void*);
    void *arg;
} thread_wrapper_t;

static DWORD WINAPI thread_wrapper(LPVOID param) {
    thread_wrapper_t *tw = (thread_wrapper_t*)param;
    tw->func(tw->arg);
    free(tw);
    return 0;
}

int thread_create(thread_t *thread, void *(*func)(void*), void *arg) {
    thread_wrapper_t *tw = malloc(sizeof(*tw));
    tw->func = func;
    tw->arg = arg;
    
    *thread = CreateThread(NULL, 0, thread_wrapper, tw, 0, NULL);
    return (*thread != NULL) ? 0 : -1;
}

int thread_join(thread_t thread) {
    WaitForSingleObject(thread, INFINITE);
    CloseHandle(thread);
    return 0;
}

void mutex_init(mutex_t *mutex) {
    InitializeCriticalSection(mutex);
}

void mutex_lock(mutex_t *mutex) {
    EnterCriticalSection(mutex);
}

void mutex_unlock(mutex_t *mutex) {
    LeaveCriticalSection(mutex);
}

void mutex_destroy(mutex_t *mutex) {
    DeleteCriticalSection(mutex);
}

#endif // Windows
// main.c - Cross-platform application
#include "platform.h"
#include "debug.h"
#include <stdio.h>
#include <stdlib.h>

typedef struct {
    mutex_t mutex;
    int counter;
    bool running;
} shared_data_t;

void *worker_thread(void *arg) {
    shared_data_t *data = (shared_data_t*)arg;
    
    INFO("Worker thread started on %s", PLATFORM_NAME);
    
    while (data->running) {
        mutex_lock(&data->mutex);
        data->counter++;
        mutex_unlock(&data->mutex);
        
        platform_sleep_ms(100);
    }
    
    INFO("Worker thread stopping");
    return NULL;
}

int main(void) {
    INFO("Starting application on %s (%d-bit)", PLATFORM_NAME, PLATFORM_BITS);
    INFO("Compiled with %s", COMPILER_NAME);
    
    platform_init();
    
    // Initialize shared data
    shared_data_t data = {0};
    data.running = true;
    mutex_init(&data.mutex);
    
    // Create worker thread
    thread_t worker;
    if (thread_create(&worker, worker_thread, &data) != 0) {
        ERROR("Failed to create thread");
        return 1;
    }
    
    // Main loop
    uint64_t start_time = platform_get_time_ns();
    
    for (int i = 0; i < 10; i++) {
        platform_sleep_ms(500);
        
        mutex_lock(&data.mutex);
        int count = data.counter;
        mutex_unlock(&data.mutex);
        
        uint64_t elapsed_ns = platform_get_time_ns() - start_time;
        INFO("Counter: %d (elapsed: %llu ms)", 
             count, (unsigned long long)(elapsed_ns / 1000000));
    }
    
    // Stop worker
    data.running = false;
    thread_join(worker);
    
    // Cleanup
    mutex_destroy(&data.mutex);
    platform_cleanup();
    
    INFO("Application finished successfully");
    return 0;
}
# Makefile - Cross-platform build system
CC = gcc
CFLAGS = -Wall -Wextra -std=c11 -O2
INCLUDES = -Iinclude
TARGET = app

UNAME_S := $(shell uname -s)

ifeq ($(UNAME_S),Linux)
    PLATFORM_SRC = src/platform_unix.c
    LIBS = -lpthread
endif

ifeq ($(UNAME_S),Darwin)
    PLATFORM_SRC = src/platform_unix.c
    LIBS = -lpthread
endif

ifeq ($(OS),Windows_NT)
    PLATFORM_SRC = src/platform_win.c
    LIBS =
    TARGET = app.exe
endif

SRCS = src/main.c src/app.c $(PLATFORM_SRC)
OBJS = $(SRCS:.c=.o)

all: $(TARGET)

$(TARGET): $(OBJS)
	$(CC) $(OBJS) -o $(TARGET) $(LIBS)

%.o: %.c
	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@

clean:
	rm -f $(OBJS) $(TARGET)

.PHONY: all clean

Conclusion

You’ve completed a comprehensive journey through C macros, preprocessor directives, and compiler attributes!

What You’ve Mastered:

Preprocessor Fundamentals (Chapters 1-8):

  • All preprocessor directives (#define, #if, #ifdef, #include, etc.)
  • Object-like and function-like macros
  • Variadic macros and VA_ARGS
  • Token pasting (##) and stringification (#)
  • Predefined macros (FILE, LINE, DATE, etc.)
  • Modern C23 features (#elifdef, VA_OPT)

Compiler Attributes (Chapters 9-10):

  • GCC/Clang attribute syntax
  • MSVC __declspec and pragmas
  • Function attributes (inline, noreturn, pure, format)
  • Variable attributes (aligned, packed, section)
  • Portable attribute wrappers

Cross-Compilation (Chapters 11-14):

  • Platform detection (Windows, Linux, macOS, BSD)
  • Architecture detection (x86, ARM, RISC-V, etc.)
  • Compiler detection and version checking
  • Portable builtin wrappers (clz, popcount, bswap)

Linux Kernel Patterns (Chapters 15-19):

  • Kernel coding style macros (min/max, ARRAY_SIZE)
  • Intrusive linked lists (list_head)
  • Hash tables (hlist)
  • The famous container_of macro
  • likely/unlikely branch prediction hints
  • Memory barriers and atomic operations
  • Lock-free data structures
  • Comprehensive debugging macros

Production Code (Chapter 20):

  • Complete cross-platform application
  • Portable threading and synchronization
  • Platform abstraction layer
  • Build system integration

Key Takeaways:

  1. The preprocessor is powerful - Use it wisely
  2. Type safety matters - container_of uses typeof() for safety
  3. Branch hints help - likely/unlikely guide compiler optimization
  4. Barriers are critical - Prevent reordering in concurrent code
  5. Portable code is possible - With careful macro design

Linux Kernel Wisdom:

The Linux kernel is a masterclass in macro usage:

  • container_of for type-safe containers
  • likely/unlikely for hot path optimization
  • Intrusive lists for zero-allocation data structures
  • Atomic operations for lock-free algorithms
  • Compile-time assertions for safety

Next Steps:

  1. Study real kernel code - linux/include/linux/
  2. Profile your code - Measure before using likely/unlikely
  3. Write portable code - Test on multiple platforms
  4. Use assertions - Catch bugs early
  5. Read compiler output - Understand macro expansion

Resources:

The preprocessor and compiler attributes are essential tools for systems programming. Master them and you’ll write code that’s fast, portable, and maintainable!

Happy coding, and may your macros expand cleanly!

Get the Complete Guide: The Complete Guide to C Macros, Preprocessor Directives, and Compiler Attributes

Prefer to read offline? Get the complete PDF, ePub, and source code bundle.

Buy Now for $19

Includes PDF, ePub, and full source code bundle. Payments securely processed via Gumroad.