c
examples
examples.c🔧c
/**
* Introduction to the C Preprocessor - Examples
*
* This file demonstrates the fundamental concepts and usage
* of the C preprocessor including directives, macros, and more.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* ============================================================
* Example 1: Object-like Macros (Constants)
* ============================================================ */
/* Simple constant definitions */
#define PI 3.14159265358979
#define E 2.71828182845905
#define MAX_BUFFER_SIZE 1024
#define APP_NAME "Preprocessor Demo"
#define APP_VERSION "1.0.0"
/* Empty macro (used for conditional compilation) */
#define FEATURE_ENABLED
void example_constants(void) {
printf("=== Example 1: Object-like Macros (Constants) ===\n\n");
printf("Application: %s v%s\n", APP_NAME, APP_VERSION);
printf("PI = %.15f\n", PI);
printf("E = %.15f\n", E);
printf("Buffer size: %d bytes\n", MAX_BUFFER_SIZE);
/* Using constant in array declaration */
char buffer[MAX_BUFFER_SIZE];
printf("Buffer array created with %d elements\n\n", MAX_BUFFER_SIZE);
(void)buffer; /* Suppress unused warning */
}
/* ============================================================
* Example 2: Function-like Macros
* ============================================================ */
/* Basic function macros */
#define SQUARE(x) ((x) * (x))
#define CUBE(x) ((x) * (x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define ABS(x) ((x) < 0 ? -(x) : (x))
/* Multi-parameter macros */
#define CLAMP(value, low, high) \
(((value) < (low)) ? (low) : (((value) > (high)) ? (high) : (value)))
#define IN_RANGE(value, low, high) \
((value) >= (low) && (value) <= (high))
void example_function_macros(void) {
printf("=== Example 2: Function-like Macros ===\n\n");
int a = 5, b = 3;
printf("a = %d, b = %d\n", a, b);
printf("SQUARE(%d) = %d\n", a, SQUARE(a));
printf("CUBE(%d) = %d\n", b, CUBE(b));
printf("MAX(%d, %d) = %d\n", a, b, MAX(a, b));
printf("MIN(%d, %d) = %d\n", a, b, MIN(a, b));
printf("ABS(-7) = %d\n", ABS(-7));
int value = 15;
printf("\nCLAMP(%d, 0, 10) = %d\n", value, CLAMP(value, 0, 10));
printf("IN_RANGE(%d, 0, 20) = %d\n", value, IN_RANGE(value, 0, 20));
printf("IN_RANGE(%d, 0, 10) = %d\n", value, IN_RANGE(value, 0, 10));
printf("\n");
}
/* ============================================================
* Example 3: Why Parentheses Matter
* ============================================================ */
/* BAD: Missing parentheses */
#define BAD_DOUBLE(x) x * 2
#define BAD_ADD(a, b) a + b
/* GOOD: Proper parentheses */
#define GOOD_DOUBLE(x) ((x) * 2)
#define GOOD_ADD(a, b) ((a) + (b))
void example_parentheses(void) {
printf("=== Example 3: Why Parentheses Matter ===\n\n");
printf("Testing with expression (3 + 4):\n");
printf("BAD_DOUBLE(3 + 4) = %d (3 + 4 * 2 = 11, wrong!)\n",
BAD_DOUBLE(3 + 4));
printf("GOOD_DOUBLE(3 + 4) = %d ((3 + 4) * 2 = 14, correct!)\n",
GOOD_DOUBLE(3 + 4));
printf("\nTesting 10 / BAD_ADD(2, 3):\n");
printf("10 / BAD_ADD(2, 3) = %d (10 / 2 + 3 = 8, wrong!)\n",
10 / BAD_ADD(2, 3));
printf("10 / GOOD_ADD(2, 3) = %d (10 / (2 + 3) = 2, correct!)\n",
10 / GOOD_ADD(2, 3));
printf("\n");
}
/* ============================================================
* Example 4: Predefined Macros
* ============================================================ */
void example_predefined_macros(void) {
printf("=== Example 4: Predefined Macros ===\n\n");
printf("__FILE__ = %s\n", __FILE__);
printf("__LINE__ = %d\n", __LINE__);
printf("__DATE__ = %s\n", __DATE__);
printf("__TIME__ = %s\n", __TIME__);
printf("__func__ = %s\n", __func__);
#ifdef __STDC__
printf("__STDC__ = %d (Standard conforming)\n", __STDC__);
#endif
#ifdef __STDC_VERSION__
printf("__STDC_VERSION__ = %ldL\n", __STDC_VERSION__);
#if __STDC_VERSION__ >= 202311L
printf(" -> C23 or later\n");
#elif __STDC_VERSION__ >= 201710L
printf(" -> C17\n");
#elif __STDC_VERSION__ >= 201112L
printf(" -> C11\n");
#elif __STDC_VERSION__ >= 199901L
printf(" -> C99\n");
#endif
#endif
printf("\n");
}
/* ============================================================
* Example 5: Stringification Operator (#)
* ============================================================ */
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define PRINT_VAR(var) printf(#var " = %d\n", var)
#define PRINT_EXPR(expr) printf(#expr " = %d\n", (expr))
void example_stringification(void) {
printf("=== Example 5: Stringification Operator (#) ===\n\n");
/* Direct stringification */
printf("STRINGIFY(hello) = %s\n", STRINGIFY(hello));
printf("STRINGIFY(123) = %s\n", STRINGIFY(123));
printf("STRINGIFY(a + b) = %s\n", STRINGIFY(a + b));
/* Two-level stringification for macro values */
#define VALUE 42
printf("\nWith VALUE defined as 42:\n");
printf("STRINGIFY(VALUE) = %s (macro name)\n", STRINGIFY(VALUE));
printf("TOSTRING(VALUE) = %s (macro value)\n", TOSTRING(VALUE));
/* Debugging with stringification */
printf("\nDebugging variables:\n");
int count = 10;
int total = 250;
PRINT_VAR(count);
PRINT_VAR(total);
printf("\nDebugging expressions:\n");
PRINT_EXPR(count * 5);
PRINT_EXPR(total / count);
PRINT_EXPR(count > 5 ? 1 : 0);
printf("\n");
}
/* ============================================================
* Example 6: Token Pasting Operator (##)
* ============================================================ */
#define CONCAT(a, b) a##b
#define MAKE_FUNC(name) void name##_function(void) { \
printf("Called " #name "_function\n"); \
}
#define DECLARE_VAR(type, prefix, num) type prefix##num
#define ACCESS_MEMBER(obj, member) obj##.##member
/* Generate functions using token pasting */
MAKE_FUNC(alpha)
MAKE_FUNC(beta)
MAKE_FUNC(gamma)
void example_token_pasting(void) {
printf("=== Example 6: Token Pasting Operator (##) ===\n\n");
/* Creating variable names */
int CONCAT(my, Variable) = 100;
int CONCAT(counter, 1) = 10;
int CONCAT(counter, 2) = 20;
printf("myVariable = %d\n", myVariable);
printf("counter1 = %d\n", counter1);
printf("counter2 = %d\n", counter2);
/* Declaring variables with generated names */
DECLARE_VAR(int, value, A) = 5;
DECLARE_VAR(int, value, B) = 10;
printf("valueA = %d, valueB = %d\n", valueA, valueB);
/* Calling generated functions */
printf("\nCalling generated functions:\n");
alpha_function();
beta_function();
gamma_function();
printf("\n");
}
/* ============================================================
* Example 7: Conditional Compilation with #ifdef/#ifndef
* ============================================================ */
/* Define some feature flags */
#define DEBUG_MODE
#define FEATURE_LOGGING
/* #define FEATURE_PROFILING */ /* Commented out - disabled */
void example_ifdef(void) {
printf("=== Example 7: Conditional Compilation (#ifdef/#ifndef) ===\n\n");
#ifdef DEBUG_MODE
printf("[DEBUG] Debug mode is ENABLED\n");
#else
printf("[INFO] Debug mode is DISABLED\n");
#endif
#ifndef DEBUG_MODE
printf("This won't print because DEBUG_MODE is defined\n");
#endif
#ifdef FEATURE_LOGGING
printf("[FEATURE] Logging is ENABLED\n");
#endif
#ifdef FEATURE_PROFILING
printf("[FEATURE] Profiling is ENABLED\n");
#else
printf("[FEATURE] Profiling is DISABLED\n");
#endif
/* Nested conditionals */
#ifdef DEBUG_MODE
#ifdef FEATURE_LOGGING
printf("[DEBUG+LOG] Both debug and logging enabled\n");
#endif
#endif
printf("\n");
}
/* ============================================================
* Example 8: Conditional Compilation with #if
* ============================================================ */
#define VERSION_MAJOR 2
#define VERSION_MINOR 5
#define BUILD_NUMBER 1023
/* Combined version number */
#define VERSION ((VERSION_MAJOR * 10000) + (VERSION_MINOR * 100) + BUILD_NUMBER)
void example_if_directive(void) {
printf("=== Example 8: Conditional Compilation (#if) ===\n\n");
printf("Version: %d.%d.%d\n", VERSION_MAJOR, VERSION_MINOR, BUILD_NUMBER);
#if VERSION_MAJOR >= 2
printf("Version 2.x or higher features available\n");
#endif
#if VERSION_MAJOR == 2 && VERSION_MINOR >= 5
printf("Version 2.5+ features available\n");
#endif
#if VERSION > 20000
printf("Modern version (> 2.0.0)\n");
#elif VERSION > 10000
printf("Version 1.x\n");
#else
printf("Legacy version (< 1.0.0)\n");
#endif
/* Using defined() operator */
#if defined(DEBUG_MODE) && defined(FEATURE_LOGGING)
printf("Debug logging available\n");
#endif
#if !defined(NDEBUG)
printf("Assertions are enabled (NDEBUG not defined)\n");
#endif
printf("\n");
}
/* ============================================================
* Example 9: Platform Detection
* ============================================================ */
void example_platform_detection(void) {
printf("=== Example 9: Platform Detection ===\n\n");
printf("Detected Platform: ");
#if defined(_WIN32) || defined(_WIN64)
printf("Windows");
#ifdef _WIN64
printf(" (64-bit)");
#else
printf(" (32-bit)");
#endif
#elif defined(__linux__)
printf("Linux");
#ifdef __ANDROID__
printf(" (Android)");
#endif
#elif defined(__APPLE__) && defined(__MACH__)
printf("macOS/iOS");
#elif defined(__unix__)
printf("Unix");
#elif defined(__FreeBSD__)
printf("FreeBSD");
#else
printf("Unknown");
#endif
printf("\n");
printf("\nCompiler: ");
#if defined(__clang__)
printf("Clang %d.%d.%d\n", __clang_major__, __clang_minor__,
__clang_patchlevel__);
#elif defined(__GNUC__)
printf("GCC %d.%d.%d\n", __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__);
#elif defined(_MSC_VER)
printf("MSVC %d\n", _MSC_VER);
#else
printf("Unknown compiler\n");
#endif
printf("\n");
}
/* ============================================================
* Example 10: Multi-line Macros
* ============================================================ */
/* Multi-line macro with do-while(0) pattern */
#define SAFE_FREE(ptr) do { \
if ((ptr) != NULL) { \
free(ptr); \
(ptr) = NULL; \
} \
} while(0)
/* Debug print macro */
#define DEBUG_PRINT(fmt, ...) do { \
fprintf(stderr, "[DEBUG] %s:%d: ", __FILE__, __LINE__); \
fprintf(stderr, fmt, ##__VA_ARGS__); \
fprintf(stderr, "\n"); \
} while(0)
/* Assertion-like macro */
#define CHECK(condition) do { \
if (!(condition)) { \
fprintf(stderr, "Check failed: %s (file %s, line %d)\n", \
#condition, __FILE__, __LINE__); \
} \
} while(0)
void example_multiline_macros(void) {
printf("=== Example 10: Multi-line Macros ===\n\n");
/* SAFE_FREE example */
int *ptr = malloc(sizeof(int));
*ptr = 42;
printf("Allocated ptr, value = %d\n", *ptr);
SAFE_FREE(ptr);
printf("After SAFE_FREE, ptr = %s\n", ptr == NULL ? "NULL" : "not null");
/* Can safely call again */
SAFE_FREE(ptr); /* No crash because it checks for NULL */
printf("Second SAFE_FREE call - no crash\n");
/* DEBUG_PRINT example */
printf("\nDEBUG_PRINT examples:\n");
DEBUG_PRINT("Application starting");
DEBUG_PRINT("Value is %d", 42);
DEBUG_PRINT("Name: %s, Age: %d", "John", 25);
/* CHECK example */
printf("\nCHECK examples:\n");
int x = 10;
CHECK(x > 5); /* Passes */
CHECK(x == 10); /* Passes */
CHECK(x < 5); /* Fails - prints message */
printf("\n");
}
/* ============================================================
* Example 11: Undef and Redefine
* ============================================================ */
void example_undef(void) {
printf("=== Example 11: #undef and Redefine ===\n\n");
#define TEMP_VALUE 100
printf("Initial TEMP_VALUE = %d\n", TEMP_VALUE);
#undef TEMP_VALUE
/* TEMP_VALUE is now undefined */
#define TEMP_VALUE 200
printf("After redefine, TEMP_VALUE = %d\n", TEMP_VALUE);
/* Common use: Override library macros */
#ifdef BUFFER_SIZE
#undef BUFFER_SIZE
#endif
#define BUFFER_SIZE 4096
printf("Custom BUFFER_SIZE = %d\n", BUFFER_SIZE);
#undef TEMP_VALUE
printf("\n");
}
/* ============================================================
* Example 12: Error and Warning Directives
* ============================================================ */
/* These would stop/warn during compilation if uncommented */
/* #error "This is a compile-time error message" */
/* #warning "This is a compile-time warning" */ /* Non-standard */
#define REQUIRED_VERSION 2
void example_error_directive(void) {
printf("=== Example 12: #error and #warning Directives ===\n\n");
/* Example of conditional error */
#if REQUIRED_VERSION < 1
#error "Version must be at least 1"
#endif
printf("Version check passed (REQUIRED_VERSION = %d)\n", REQUIRED_VERSION);
/* Example usage patterns */
printf("\nCommon #error patterns:\n");
printf(" #error \"Missing configuration\"\n");
printf(" #error \"Platform not supported\"\n");
printf(" #error \"Feature X requires Y to be defined\"\n");
printf("\n");
}
/* ============================================================
* Example 13: Line Control (#line)
* ============================================================ */
void example_line_directive(void) {
printf("=== Example 13: #line Directive ===\n\n");
printf("Before #line:\n");
printf(" __LINE__ = %d\n", __LINE__);
printf(" __FILE__ = %s\n", __FILE__);
#line 1000 "virtual_file.c"
printf("\nAfter #line 1000 \"virtual_file.c\":\n");
printf(" __LINE__ = %d\n", __LINE__);
printf(" __FILE__ = %s\n", __FILE__);
/* Reset to approximate actual line */
#line 250
printf("\nAfter #line 250 (reset filename):\n");
printf(" __LINE__ = %d\n", __LINE__);
printf("\n(Note: #line is mainly used by code generators)\n\n");
}
/* ============================================================
* Example 14: Pragma Directive
* ============================================================ */
/* #pragma once - common header guard (shown in comments) */
/* #pragma pack(push, 1) - struct packing */
void example_pragma(void) {
printf("=== Example 14: #pragma Directive ===\n\n");
printf("Common #pragma directives:\n\n");
printf(" #pragma once\n");
printf(" - Include guard (non-standard but widely supported)\n\n");
printf(" #pragma pack(push, 1)\n");
printf(" #pragma pack(pop)\n");
printf(" - Control struct member alignment\n\n");
printf(" #pragma message(\"text\")\n");
printf(" - Display message during compilation\n\n");
printf(" #pragma GCC diagnostic ignored \"-Wunused\"\n");
printf(" - Suppress specific warnings (GCC/Clang)\n\n");
printf(" #pragma region / #pragma endregion\n");
printf(" - Code folding regions (IDE support)\n\n");
/* GCC-specific: Display message */
#ifdef __GNUC__
#pragma message("Compiling with GCC")
#endif
}
/* ============================================================
* Example 15: Complete Practical Example
* ============================================================ */
/* Configuration macros */
#define PROJECT_NAME "ConfigDemo"
#define LOG_LEVEL_DEBUG 0
#define LOG_LEVEL_INFO 1
#define LOG_LEVEL_WARN 2
#define LOG_LEVEL_ERROR 3
#define CURRENT_LOG_LEVEL LOG_LEVEL_DEBUG
/* Logging macros with level filtering */
#define LOG_DEBUG(msg) do { \
if (CURRENT_LOG_LEVEL <= LOG_LEVEL_DEBUG) \
printf("[DEBUG] %s\n", msg); \
} while(0)
#define LOG_INFO(msg) do { \
if (CURRENT_LOG_LEVEL <= LOG_LEVEL_INFO) \
printf("[INFO] %s\n", msg); \
} while(0)
#define LOG_WARN(msg) do { \
if (CURRENT_LOG_LEVEL <= LOG_LEVEL_WARN) \
printf("[WARN] %s\n", msg); \
} while(0)
#define LOG_ERROR(msg) do { \
if (CURRENT_LOG_LEVEL <= LOG_LEVEL_ERROR) \
printf("[ERROR] %s\n", msg); \
} while(0)
/* Assert macro */
#ifndef NDEBUG
#define ASSERT(cond) do { \
if (!(cond)) { \
fprintf(stderr, "Assertion failed: %s\n", #cond); \
fprintf(stderr, " File: %s, Line: %d\n", __FILE__, __LINE__); \
abort(); \
} \
} while(0)
#else
#define ASSERT(cond) ((void)0)
#endif
/* Array size macro */
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
/* Unused parameter silencer */
#define UNUSED(x) ((void)(x))
void example_practical(void) {
printf("=== Example 15: Practical Macros ===\n\n");
printf("Project: %s\n\n", PROJECT_NAME);
/* Logging examples */
printf("Logging (level = DEBUG):\n");
LOG_DEBUG("Entering function");
LOG_INFO("Processing data");
LOG_WARN("Resource running low");
LOG_ERROR("Operation failed");
/* Array size */
int numbers[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
printf("\nArray has %zu elements\n", ARRAY_SIZE(numbers));
/* Unused parameter */
int unused_var = 42;
UNUSED(unused_var);
printf("Unused variable silenced without warning\n");
/* Assert (won't fail here) */
int value = 10;
ASSERT(value > 0);
ASSERT(value == 10);
printf("Assertions passed\n");
printf("\n");
}
/* ============================================================
* Main Function
* ============================================================ */
int main(void) {
printf("\n");
printf("╔══════════════════════════════════════════════════════════╗\n");
printf("║ Introduction to C Preprocessor - Examples ║\n");
printf("╚══════════════════════════════════════════════════════════╝\n\n");
example_constants();
example_function_macros();
example_parentheses();
example_predefined_macros();
example_stringification();
example_token_pasting();
example_ifdef();
example_if_directive();
example_platform_detection();
example_multiline_macros();
example_undef();
example_error_directive();
example_line_directive();
example_pragma();
example_practical();
printf("╔══════════════════════════════════════════════════════════╗\n");
printf("║ All examples complete! ║\n");
printf("╚══════════════════════════════════════════════════════════╝\n\n");
return 0;
}