Before your C code is ever compiled, it passes through a crucial first step: the preprocessor. The preprocessor handles directives that begin with the # symbol, performing text manipulation, file inclusion, conditional compilation, and macro expansion. Understanding preprocessor directives is essential for writing portable, maintainable, and efficient C code.
What is the C Preprocessor?
The preprocessor is a text processor that runs before the compiler. It:
- Removes comments
- Includes header files
- Expands macros
- Handles conditional compilation
- Generates warnings and errors
All preprocessor directives begin with # and don't end with semicolons.
Source Code (.c) → Preprocessor → Modified Source → Compiler → Object Code ↑ Directives (#include, #define, etc.)
1. File Inclusion: #include
The #include directive inserts the contents of another file into your source code.
Two Forms:
// System headers - search in system directories first #include <stdio.h> #include <stdlib.h> #include <math.h> // User headers - search in current directory first #include "myheader.h" #include "utils/helpers.h" #include "../common/defs.h"
How It Works:
// File: math_utils.h #ifndef MATH_UTILS_H #define MATH_UTILS_H #define PI 3.14159 int square(int x); #endif // File: main.c #include <stdio.h> #include "math_utils.h" // Contents of math_utils.h are inserted here int main() { printf("PI = %f\n", PI); printf("Square of 5 = %d\n", square(5)); return 0; } 2. Macro Definition: #define
Macros are text substitutions that happen before compilation.
Simple Macros (Object-like):
#include <stdio.h> #define PI 3.14159265359 #define MAX_SIZE 100 #define APP_NAME "MyApplication" #define DEBUG 1 int main() { double radius = 5.0; double area = PI * radius * radius; // PI replaced with 3.14159265359 printf("%s: Area = %.2f\n", APP_NAME, area); printf("MAX_SIZE = %d\n", MAX_SIZE); return 0; } Function-like Macros:
#include <stdio.h> // Simple function-like macros #define SQUARE(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-line macros (use backslash) #define PRINT_VAR(var) \ printf(#var " = %d\n", var); \ printf("Address of " #var ": %p\n", (void*)&var) // Debug printing macro #define DEBUG_PRINT(fmt, ...) \ do { \ if (DEBUG) { \ printf("[DEBUG] %s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ } \ } while(0) int main() { int x = 5, y = 3; printf("SQUARE(%d) = %d\n", x, SQUARE(x)); printf("MAX(%d, %d) = %d\n", x, y, MAX(x, y)); printf("ABS(-10) = %d\n", ABS(-10)); int value = 42; PRINT_VAR(value); DEBUG_PRINT("x = %d, y = %d\n", x, y); return 0; } Output:
SQUARE(5) = 25 MAX(5, 3) = 5 ABS(-10) = 10 value = 42 Address of value: 0x7ffc12345678 [DEBUG] test.c:35: x = 5, y = 3
Important Macro Pitfalls:
// WRONG - operator precedence issues #define BAD_SQUARE(x) x * x // BAD_SQUARE(2+3) expands to 2+3*2+3 = 11, not 25! // CORRECT - use parentheses #define GOOD_SQUARE(x) ((x) * (x)) // WRONG - side effects #define BAD_MAX(a, b) ((a) > (b) ? (a) : (b)) // BAD_MAX(++x, y) expands to ((++x) > (y) ? (++x) : (y)) - increments twice! // Better to use inline functions for complex operations static inline int max(int a, int b) { return a > b ? a : b; } 3. Stringification and Token Pasting
Stringification (#) - Convert parameter to string:
#include <stdio.h> #define STRINGIFY(x) #x #define PRINT_INT(x) printf(#x " = %d\n", x) #define WARN_IF(expr) \ do { \ if (expr) { \ fprintf(stderr, "Warning: " #expr "\n"); \ } \ } while(0) int main() { printf("STRINGIFY(hello) = %s\n", STRINGIFY(hello)); int value = 42; PRINT_INT(value); int x = 5; WARN_IF(x > 10); // Nothing printed WARN_IF(x < 10); // Prints "Warning: x < 10" return 0; } Output:
STRINGIFY(hello) = hello value = 42 Warning: x < 10
Token Pasting (##) - Concatenate tokens:
#include <stdio.h> #define CONCAT(a, b) a ## b #define MAKE_VAR(name, num) name ## num #define GENERATE_FUNC(type) \ type type ## _max(type a, type b) { \ return a > b ? a : b; \ } // Generate functions for different types GENERATE_FUNC(int) GENERATE_FUNC(double) int main() { int xy = 100; int var1 = 10; int var2 = 20; printf("CONCAT(x, y) = %d\n", CONCAT(x, y)); // Refers to variable xy printf("MAKE_VAR(var, 1) = %d\n", MAKE_VAR(var, 1)); // Refers to var1 printf("int_max(5, 10) = %d\n", int_max(5, 10)); printf("double_max(3.14, 2.71) = %f\n", double_max(3.14, 2.71)); return 0; } 4. Conditional Compilation
Conditional compilation allows you to include or exclude code based on conditions.
Basic Conditionals:
#include <stdio.h> #define DEBUG 1 #define VERSION 2 int main() { #if DEBUG printf("Debug mode is ON\n"); #endif #if VERSION == 1 printf("Running version 1 code\n"); #elif VERSION == 2 printf("Running version 2 code\n"); #else printf("Running unknown version\n"); #endif // #ifdef - if defined #ifdef DEBUG printf("DEBUG is defined\n"); #endif // #ifndef - if not defined #ifndef RELEASE printf("RELEASE is not defined\n"); #endif return 0; } Platform-Specific Code:
#include <stdio.h> // Detect operating system #ifdef _WIN32 #define PLATFORM "Windows" #include <windows.h> #define CLEAR_SCREEN system("cls") #elif __linux__ #define PLATFORM "Linux" #include <unistd.h> #define CLEAR_SCREEN system("clear") #elif __APPLE__ #define PLATFORM "macOS" #include <unistd.h> #define CLEAR_SCREEN system("clear") #else #define PLATFORM "Unknown" #define CLEAR_SCREEN printf("\n") #endif // Detect compiler #ifdef __GNUC__ #define COMPILER "GCC" #define COMPILER_VERSION __GNUC__ #elif _MSC_VER #define COMPILER "MSVC" #define COMPILER_VERSION _MSC_VER #else #define COMPILER "Unknown" #endif int main() { printf("Platform: %s\n", PLATFORM); printf("Compiler: %s\n", COMPILER); printf("Compiler version: %d\n", COMPILER_VERSION); printf("\nClearing screen in 3 seconds...\n"); sleep(3); CLEAR_SCREEN; return 0; } Feature Testing:
#include <stdio.h> // Feature flags #define FEATURE_ADVANCED_MATH 1 #define FEATURE_GRAPHICS 0 #define FEATURE_NETWORKING 1 int main() { #if FEATURE_ADVANCED_MATH printf("Advanced math features enabled\n"); // Include complex math code #endif #if FEATURE_GRAPHICS printf("Graphics features enabled\n"); // Initialize graphics #else printf("Running in text-only mode\n"); #endif #if FEATURE_NETWORKING printf("Networking enabled\n"); // Setup network connections #endif return 0; } 5. Header Guards
Header guards prevent multiple inclusions of the same header file.
// File: myheader.h #ifndef MYHEADER_H // If not defined #define MYHEADER_H // Define it // Header content goes here #define MAX_BUFFER 1024 typedef struct { int id; char name[50]; } Person; void printPerson(Person *p); #endif // End of guard Modern alternative using #pragma once:
// File: myheader.h #pragma once // Simpler, but not standard in all compilers #define MAX_BUFFER 1024 typedef struct { int id; char name[50]; } Person; void printPerson(Person *p); 6. Predefined Macros
The C standard defines several useful macros:
#include <stdio.h> int main() { printf("File: %s\n", __FILE__); printf("Date: %s\n", __DATE__); printf("Time: %s\n", __TIME__); printf("Line: %d\n", __LINE__); printf("Function: %s\n", __func__); // Not a macro, but useful printf("Standard: %ld\n", __STDC_VERSION__); #ifdef __cplusplus printf("Compiled as C++\n"); #else printf("Compiled as C\n"); #endif // Line control #line 100 "newfile.c" printf("Now at line %d in file %s\n", __LINE__, __FILE__); return 0; } Common predefined macros:
| Macro | Description |
|---|---|
__FILE__ | Current filename (string) |
__LINE__ | Current line number (integer) |
__DATE__ | Compilation date (string) |
__TIME__ | Compilation time (string) |
__STDC__ | 1 if compiler conforms to ANSI C |
__STDC_VERSION__ | C standard version (e.g., 201112L for C11) |
__func__ | Current function name (not a macro) |
7. #error and #warning Directives
Generate custom errors and warnings during preprocessing:
#include <stdio.h> #ifndef VERSION #error "VERSION must be defined" #endif #if VERSION < 2 #warning "Version 1 is deprecated, please upgrade to version 2" #endif #ifdef _WIN32 #define PATH_SEPARATOR '\\' #elif __linux__ #define PATH_SEPARATOR '/' #else #error "Unsupported platform" #endif int main() { printf("Using path separator: %c\n", PATH_SEPARATOR); printf("Version %d\n", VERSION); return 0; } 8. #pragma Directive
The #pragma directive offers compiler-specific features:
#include <stdio.h> // Pack structures (remove padding) #pragma pack(1) typedef struct { char c; int i; short s; } PackedStruct; #pragma pack() // Reset to default // Disable specific warnings (MSVC) #pragma warning(disable : 4996) // Disable unsafe function warning // GCC optimization pragmas #pragma GCC optimize("O3") #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-variable" // Linker directives (MSVC) #pragma comment(lib, "user32.lib") #pragma comment(linker, "/SUBSYSTEM:CONSOLE") int main() { printf("Size of normal struct: %lu\n", sizeof(struct { char c; int i; short s; })); printf("Size of packed struct: %lu\n", sizeof(PackedStruct)); #pragma GCC diagnostic pop return 0; } 9. # and ## Advanced Examples
Building lookup tables with macros:
#include <stdio.h> // Generate enum and string array from same list #define COLOR_LIST \ COLOR(RED) \ COLOR(GREEN) \ COLOR(BLUE) \ COLOR(YELLOW) \ COLOR(MAGENTA) \ COLOR(CYAN) // Generate enum #define COLOR(name) name, typedef enum { COLOR_LIST } Color; #undef COLOR // Generate string array #define COLOR(name) #name, const char* color_names[] = { COLOR_LIST }; #undef COLOR // Debug macro with automatic variable names #define DEBUG_VAR(var) \ printf("%s = %d (at %s:%d)\n", #var, var, __FILE__, __LINE__) // Generate getter/setter macros #define DEFINE_GETTER(type, field) \ type get_##field(type *obj) { \ return obj->field; \ } #define DEFINE_SETTER(type, field) \ void set_##field(type *obj, type value) { \ obj->field = value; \ } typedef struct { int x; int y; } Point; DEFINE_GETTER(int, x) DEFINE_SETTER(int, x) int main() { for(int i = 0; i < sizeof(color_names)/sizeof(char*); i++) { printf("Color %d: %s\n", i, color_names[i]); } int value = 42; DEBUG_VAR(value); Point p = {10, 20}; printf("get_x(&p) = %d\n", get_x(&p)); set_x(&p, 99); printf("After set_x: %d\n", get_x(&p)); return 0; } 10. Practical Examples
Example 1: Configurable Logging System
#include <stdio.h> #include <time.h> // Log levels #define LOG_LEVEL_NONE 0 #define LOG_LEVEL_ERROR 1 #define LOG_LEVEL_WARN 2 #define LOG_LEVEL_INFO 3 #define LOG_LEVEL_DEBUG 4 // Set current log level (can be defined during compilation) // gcc -DLOG_LEVEL=3 program.c #ifndef LOG_LEVEL #define LOG_LEVEL LOG_LEVEL_INFO #endif // ANSI color codes for terminal output #ifdef _WIN32 #define COLOR_RED "" #define COLOR_YELLOW "" #define COLOR_GREEN "" #define COLOR_CYAN "" #define COLOR_RESET "" #else #define COLOR_RED "\x1b[31m" #define COLOR_YELLOW "\x1b[33m" #define COLOR_GREEN "\x1b[32m" #define COLOR_CYAN "\x1b[36m" #define COLOR_RESET "\x1b[0m" #endif // Logging macros #define LOG_ERROR(fmt, ...) \ do { \ if (LOG_LEVEL >= LOG_LEVEL_ERROR) { \ fprintf(stderr, COLOR_RED "[ERROR] " fmt COLOR_RESET "\n", ##__VA_ARGS__); \ } \ } while(0) #define LOG_WARN(fmt, ...) \ do { \ if (LOG_LEVEL >= LOG_LEVEL_WARN) { \ fprintf(stderr, COLOR_YELLOW "[WARN] " fmt COLOR_RESET "\n", ##__VA_ARGS__); \ } \ } while(0) #define LOG_INFO(fmt, ...) \ do { \ if (LOG_LEVEL >= LOG_LEVEL_INFO) { \ printf(COLOR_GREEN "[INFO] " fmt COLOR_RESET "\n", ##__VA_ARGS__); \ } \ } while(0) #define LOG_DEBUG(fmt, ...) \ do { \ if (LOG_LEVEL >= LOG_LEVEL_DEBUG) { \ printf(COLOR_CYAN "[DEBUG] %s:%d: " fmt COLOR_RESET "\n", \ __FILE__, __LINE__, ##__VA_ARGS__); \ } \ } while(0) // Timestamp macro #define LOG_WITH_TIME(level, fmt, ...) \ do { \ time_t now = time(NULL); \ struct tm *tm = localtime(&now); \ char timebuf[20]; \ strftime(timebuf, sizeof(timebuf), "%H:%M:%S", tm); \ level("[%s] " fmt, timebuf, ##__VA_ARGS__); \ } while(0) int main() { LOG_INFO("Application started with log level %d", LOG_LEVEL); int x = 42; LOG_DEBUG("x = %d", x); LOG_WARN("Low memory warning"); if (x > 100) { LOG_ERROR("Invalid value: %d", x); } LOG_WITH_TIME(LOG_INFO, "Processing complete"); return 0; } Example 2: Cross-Platform Directory Operations
#include <stdio.h> // Platform detection #if defined(_WIN32) || defined(_WIN64) #define PLATFORM_WINDOWS 1 #include <windows.h> #include <direct.h> #define MKDIR(path) _mkdir(path) #define PATH_SEP '\\' #define PATH_SEP_STR "\\" #define GETCWD _getcwd #elif defined(__linux__) || defined(__APPLE__) #define PLATFORM_POSIX 1 #include <sys/stat.h> #include <unistd.h> #define MKDIR(path) mkdir(path, 0755) #define PATH_SEP '/' #define PATH_SEP_STR "/" #define GETCWD getcwd #else #error "Unsupported platform" #endif // Build path macro #define BUILD_PATH(dir, file) dir PATH_SEP_STR file // Check directory exists macro #ifdef PLATFORM_WINDOWS #define DIR_EXISTS(path) (GetFileAttributes(path) != INVALID_FILE_ATTRIBUTES && \ (GetFileAttributes(path) & FILE_ATTRIBUTE_DIRECTORY)) #else #define DIR_EXISTS(path) (access(path, F_OK) == 0) #endif // Safe string concatenation macro #define SAFE_STRCAT(dest, src) \ do { \ strncat(dest, src, sizeof(dest) - strlen(dest) - 1); \ } while(0) int main() { char cwd[256]; char path[256] = ""; if (GETCWD(cwd, sizeof(cwd)) != NULL) { printf("Current directory: %s\n", cwd); } // Build path SAFE_STRCAT(path, cwd); SAFE_STRCAT(path, PATH_SEP_STR); SAFE_STRCAT(path, "data"); printf("Full path: %s\n", path); if (DIR_EXISTS(path)) { printf("Directory exists\n"); } else { printf("Directory doesn't exist\n"); if (MKDIR(path) == 0) { printf("Directory created successfully\n"); } else { printf("Failed to create directory\n"); } } return 0; } 11. Preprocessor Operators
#include <stdio.h> // defined() operator #if defined(DEBUG) && defined(_WIN32) #define PLATFORM_DEBUG "Windows Debug" #elif defined(DEBUG) && defined(__linux__) #define PLATFORM_DEBUG "Linux Debug" #endif // # and ## in combination #define MAKE_WRAPPER(type) \ type wrap_##type(type (*func)(type), type arg) { \ printf("Calling " #type " function\n"); \ return func(arg); \ } // Generate wrapper for int functions MAKE_WRAPPER(int) int square(int x) { return x * x; } int main() { printf("Square of 5: %d\n", wrap_int(square, 5)); return 0; } 12. Preprocessor Directives Summary
| Directive | Purpose | Example |
|---|---|---|
#include | Include file | #include <stdio.h> |
#define | Define macro | #define MAX 100 |
#undef | Undefine macro | #undef MAX |
#if | Conditional | #if VERSION > 2 |
#ifdef | If defined | #ifdef DEBUG |
#ifndef | If not defined | #ifndef HEADER_H |
#else | Else clause | #else |
#elif | Else if | #elif VERSION == 3 |
#endif | End conditional | #endif |
#error | Generate error | #error "Invalid config" |
#warning | Generate warning | #warning "Deprecated" |
#pragma | Compiler-specific | #pragma pack(1) |
#line | Set line number | #line 100 "file.c" |
# | Stringification | #x becomes "x" |
## | Token pasting | x ## y becomes xy |
Best Practices
- Use parentheses in macros: Always wrap macro parameters and entire expressions
- Avoid side effects in macro arguments: Macros can evaluate arguments multiple times
- Use
do { ... } while(0)for multi-statement macros: Ensures proper semicolon behavior - Use header guards: Prevent multiple inclusions
- Capitalize macro names: Convention to distinguish from functions
- Consider inline functions instead of complex macros: Better type checking
- Document complex macros: Explain what they do and how to use them
- Use
#ifdeffor feature detection: Test for compiler/platform features
Common Mistakes Checklist
- [ ] Forgetting parentheses in macros
- [ ] Multiple evaluation of arguments with side effects
- [ ] Missing backslash for multi-line macros
- [ ] Semicolon after
#define(not needed) - [ ] Spaces in macro name (
#define MAX SIZE 100creates two macros) - [ ] Not using header guards
- [ ] Overusing macros when functions would be better
- [ ] Platform-specific code without proper checks
Conclusion
The C preprocessor is a powerful tool that operates before compilation, enabling code reuse, conditional compilation, and compile-time code generation. While modern C encourages using const and inline functions where possible, preprocessor directives remain essential for:
- Header guards to prevent multiple inclusions
- Conditional compilation for platform-specific code
- Macros for simple text substitutions and compile-time constants
- Debugging aids that can be compiled out
- Code generation through token pasting and stringification
Understanding preprocessor directives allows you to write more portable, maintainable, and efficient C code. However, with great power comes responsibility—overusing the preprocessor can make code hard to debug and maintain. The key is knowing when to use preprocessor features and when to use standard C language constructs instead.
Complete C Programming Guide + Compilers Collection
1. C srand() Function – Understanding Seed Initialization
https://macronepal.com/understanding-the-c-srand-function
Explains how srand() initializes the pseudo-random number generator in C by setting a seed value. Using the same seed produces the same sequence, while time(NULL) gives different results each run.
2. C rand() Function Mechanics and Limitations
https://macronepal.com/c-rand-function-mechanics-and-limitations
Explains how rand() generates pseudo-random numbers between 0 and RAND_MAX, its deterministic nature, and limitations for security use cases.
3. C log() Function
https://macronepal.com/c-log-function-2
Covers natural logarithm calculation using <math.h> and its applications.
4. Mastering Date and Time in C
https://macronepal.com/mastering-date-and-time-in-c
Explains <time.h> functions like time(), clock(), difftime(), and struct tm.
5. Mastering time_t Type in C
https://macronepal.com/mastering-the-c-time_t-type-for-time-management
Explains time representation as seconds since Unix epoch and conversion functions.
6. C exp() Function
https://macronepal.com/c-exp-function-mechanics-and-implementation
Explains exponential function exp(x) and its scientific applications.
7. C log() Function (Alternate Guide)
https://macronepal.com/c-log-function
Comparison of log() and log10() with usage examples.
8. C log10() Function
https://macronepal.com/mastering-the-log10-function-in-c
Explains base-10 logarithm for engineering and scientific applications.
9. C tan() Function
https://macronepal.com/understanding-the-c-tan-function
Explains tangent function and radian-based calculations.
10. Random Numbers in C (Secure vs Predictable)
https://macronepal.com/mastering-c-random-numbers-for-secure-and-predictable-applications
Explains difference between rand() and secure randomness methods.
11. Free Online C Compiler
https://macronepal.com/free-online-c-code-compiler-2
Browser-based compiler for testing C programs instantly.
C Functions, Arguments, Parameters & Flow
Mastering Functions in C – Complete Guide
https://macronepal.com/c/mastering-functions-in-c-a-complete-guide/
Covers function structure, modular programming, and real-world usage.
Function Arguments in C
https://macronepal.com/c-function-arguments/
Explains how arguments are passed and used in function calls.
Function Parameters in C
https://macronepal.com/c-function-parameters/
Explains defining inputs for functions and matching them with arguments.
Function Declarations in C
https://macronepal.com/c-function-declarations-syntax-rules-and-best-practices/
Covers prototypes, syntax rules, and best practices.
Function Calls in C
https://macronepal.com/understanding-function-calls-in-c-syntax-mechanics-and-best-practices/
Explains execution flow and parameter handling during function calls.
Void Functions in C
https://macronepal.com/understanding-void-functions-in-c-syntax-patterns-and-best-practices/
Explains functions that do not return values.
Return Values in C
https://macronepal.com/c-return-values-mechanics-types-and-best-practices/
Explains different return types and how functions return results.
Pass-by-Value in C
https://macronepal.com/aws/understanding-pass-by-value-in-c-mechanics-implications-and-best-practices/
Explains how copies of variables are passed into functions.
Pass-by-Reference in C
https://macronepal.com/c/understanding-pass-by-reference-in-c-pointers-semantics-and-safe-practices/
Explains using pointers to modify original variables.
C strstr() Function
https://macronepal.com/aws/c-strstr-function/
Explains substring search inside strings in C.
C Preprocessor & Macros
https://macronepal.com/mastering-c-variadic-macros-for-flexible-debugging/
https://macronepal.com/mastering-the-stdc-macro-in-c/
https://macronepal.com/c-time-macro-mechanics-and-usage/
https://macronepal.com/understanding-the-c-date-macro/
https://macronepal.com/c-file-type/
https://macronepal.com/mastering-c-line-macro-for-debugging-and-diagnostics/
https://macronepal.com/mastering-predefined-macros-in-c/
https://macronepal.com/c-error-directive-mechanics-and-usage/
https://macronepal.com/understanding-the-c-pragma-directive/
https://macronepal.com/c-include-directive/
C Structures, Memory, Scope & Linkage
https://macronepal.com/mastering-structures-in-c/
https://macronepal.com/c-structure-declaration-mechanics-and-usage/
https://macronepal.com/c-structure-initialization-mechanics-and-best-practices/
https://macronepal.com/mastering-c-structure-member-access-for-reliable-data-handling/
https://macronepal.com/c-nested-structures/
https://macronepal.com/mastering-arrays-of-structures-in-c/
https://macronepal.com/c-structure-pointers-mechanics-and-implementation/
https://macronepal.com/understanding-c-structure-parameter-passing-mechanics/
https://macronepal.com/mastering-c-returning-structures-for-efficient-data-flow/
https://macronepal.com/c-self-referential-structures/
https://macronepal.com/mastering-structure-alignment-in-c/
https://macronepal.com/c-structure-padding-mechanics-and-optimization/
https://macronepal.com/understanding-c-flexible-array-members-mechanics-and-usage/
https://macronepal.com/mastering-c-anonymous-structures-for-flattened-data-layouts/
https://macronepal.com/c-unions/
https://macronepal.com/mastering-c-name-mangling-and-symbol-decoration/
https://macronepal.com/c-no-linkage-mechanics-and-scope-isolation/
https://macronepal.com/understanding-c-internal-linkage-mechanics-and-architecture/
C Scope, Storage Classes & Typedef
https://macronepal.com/mastering-function-prototype-scope-in-c/
https://macronepal.com/c-function-scope-mechanics-and-visibility/
https://macronepal.com/understanding-c-file-scope-mechanics-and-architecture/
https://macronepal.com/mastering-c-scope-rules-for-predictable-name-resolution/
https://macronepal.com/c-scope-rules/
https://macronepal.com/mastering-c-register-storage-class-for-historical-context-and-modern-alternatives/
https://macronepal.com/mastering-_thread_local-in-c/
https://macronepal.com/c-extern-storage-class-mechanics-and-usage/
https://macronepal.com/understanding-the-c-static-storage-class-mechanics-and-usage/
https://macronepal.com/c-auto-storage-class/
https://macronepal.com/c-typedef-with-pointers/
Extra Articles
https://macronepal.com/13757-2/
https://macronepal.com/13748-2/
https://macronepal.com/13747-2/
https://macronepal.com/13746-2/
https://macronepal.com/13745-2/
https://macronepal.com/13708-2/
https://macronepal.com/13707-2/
https://macronepal.com/13702-2/
Online Compilers
https://macronepal.com/free-html-online-code-compiler/
https://macronepal.com/free-online-python-code-compiler/
https://macronepal.com/free-online-python2-code-compiler/
https://macronepal.com/free-online-java-code-compiler/
https://macronepal.com/free-online-javascript-code-compiler/
https://macronepal.com/free-online-node-js-code-compiler/
https://macronepal.com/free-online-c-code-compiler/
https://macronepal.com/free-online-c-code-compiler-2/
https://macronepal.com/free-online-c-code-compiler-3/
https://macronepal.com/free-online-php-code-compiler/
https://macronepal.com/free-online-ruby-code-compiler/
https://macronepal.com/free-online-perl-code-compiler/
https://macronepal.com/free-online-lua-code-compiler/
https://macronepal.com/free-online-tcl-code-compiler/
https://macronepal.com/free-online-groovy-code-compiler/
https://macronepal.com/free-online-j-shell-code-compiler/
https://macronepal.com/free-online-haskell-code-compiler/
https://macronepal.com/free-online-scala-code-compiler/
https://macronepal.com/free-online-common-lisp-code-compiler/
https://macronepal.com/free-online-d-code-compiler/
https://macronepal.com/free-online-ada-code-compiler/
https://macronepal.com/free-erlang-code-compiler/
https://macronepal.com/free-online-assembly-code-compiler/
