Enumerations (enum) are one of C's most elegant features for creating readable, maintainable code. They allow programmers to define a set of named integer constants, making code more expressive and less error-prone. Whether you're managing state machines, handling error codes, or defining configuration options, enums provide type safety and clarity that bare integers cannot match.
What is an Enumeration?
An enumeration is a user-defined type consisting of a set of named integer constants called enumerators. Each enumerator corresponds to an integer value, making enums perfect for representing a fixed set of related values.
Basic Syntax:
enum enum_name { enumerator1, enumerator2, enumerator3, // ... }; Declaring and Using Enums
1. Simple Enum Declaration
#include <stdio.h> // Define a simple enum for days of the week enum Day { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY }; int main() { enum Day today = WEDNESDAY; if (today == WEDNESDAY) { printf("It's hump day!\n"); } // Enums are integers underneath printf("SUNDAY = %d\n", SUNDAY); // Output: 0 printf("MONDAY = %d\n", MONDAY); // Output: 1 printf("SATURDAY = %d\n", SATURDAY); // Output: 6 return 0; } 2. Enum with Custom Values
#include <stdio.h> enum HttpStatus { OK = 200, CREATED = 201, ACCEPTED = 202, BAD_REQUEST = 400, UNAUTHORIZED = 401, FORBIDDEN = 403, NOT_FOUND = 404, INTERNAL_ERROR = 500, NOT_IMPLEMENTED = 501 }; enum ErrorLevel { DEBUG = 5, // Explicit value INFO, // Automatically 6 WARNING, // Automatically 7 ERROR = 10, // Explicit value CRITICAL, // Automatically 11 FATAL = 20 // Explicit value }; int main() { enum HttpStatus status = NOT_FOUND; printf("HTTP %d: ", status); switch (status) { case OK: printf("OK\n"); break; case NOT_FOUND: printf("Not Found\n"); break; default: printf("Other status\n"); } printf("DEBUG = %d\n", DEBUG); // 5 printf("INFO = %d\n", INFO); // 6 printf("WARNING = %d\n", WARNING); // 7 printf("ERROR = %d\n", ERROR); // 10 printf("CRITICAL = %d\n", CRITICAL); // 11 printf("FATAL = %d\n", FATAL); // 20 return 0; } 3. Anonymous Enums
#include <stdio.h> // Anonymous enum - useful for constants without creating a type enum { MAX_BUFFER_SIZE = 4096, MAX_CONNECTIONS = 100, TIMEOUT_SECONDS = 30, RETRY_COUNT = 3 }; int main() { char buffer[MAX_BUFFER_SIZE]; int connections[MAX_CONNECTIONS]; printf("Buffer size: %d\n", MAX_BUFFER_SIZE); printf("Max connections: %d\n", MAX_CONNECTIONS); printf("Timeout: %d seconds\n", TIMEOUT_SECONDS); printf("Retry count: %d\n", RETRY_COUNT); return 0; } Advanced Enum Techniques
1. Using typedef with Enums
#include <stdio.h> // Define enum type with typedef typedef enum { RED, GREEN, BLUE, YELLOW, CYAN, MAGENTA, BLACK, WHITE } Color; // Function that takes Color parameter void printColor(Color c) { switch (c) { case RED: printf("Red\n"); break; case GREEN: printf("Green\n"); break; case BLUE: printf("Blue\n"); break; case YELLOW: printf("Yellow\n"); break; case CYAN: printf("Cyan\n"); break; case MAGENTA: printf("Magenta\n"); break; case BLACK: printf("Black\n"); break; case WHITE: printf("White\n"); break; default: printf("Unknown color\n"); } } int main() { Color favorite = BLUE; Color background = BLACK; printf("Favorite color: "); printColor(favorite); printf("Background: "); printColor(background); return 0; } 2. Enums with Bit Flags
#include <stdio.h> // Permission flags using enum typedef enum { PERM_NONE = 0, PERM_READ = 1 << 0, // 1 PERM_WRITE = 1 << 1, // 2 PERM_EXECUTE = 1 << 2, // 4 PERM_DELETE = 1 << 3, // 8 PERM_ALL = PERM_READ | PERM_WRITE | PERM_EXECUTE | PERM_DELETE // 15 } Permission; // Check if permission has specific flag int hasPermission(Permission userPerm, Permission checkPerm) { return (userPerm & checkPerm) == checkPerm; } // Add permission Permission addPermission(Permission current, Permission add) { return current | add; } // Remove permission Permission removePermission(Permission current, Permission remove) { return current & ~remove; } void printPermissions(Permission p) { printf("Permissions: "); if (p & PERM_READ) printf("READ "); if (p & PERM_WRITE) printf("WRITE "); if (p & PERM_EXECUTE) printf("EXECUTE "); if (p & PERM_DELETE) printf("DELETE "); if (p == PERM_NONE) printf("NONE"); printf("\n"); } int main() { Permission user = PERM_READ | PERM_WRITE; printPermissions(user); // READ WRITE printf("Can read? %s\n", hasPermission(user, PERM_READ) ? "Yes" : "No"); printf("Can execute? %s\n", hasPermission(user, PERM_EXECUTE) ? "Yes" : "No"); // Add execute permission user = addPermission(user, PERM_EXECUTE); printPermissions(user); // READ WRITE EXECUTE // Remove write permission user = removePermission(user, PERM_WRITE); printPermissions(user); // READ EXECUTE return 0; } 3. Enums for State Machines
#include <stdio.h> #include <stdbool.h> // Traffic light state machine typedef enum { STATE_RED, STATE_RED_YELLOW, // Some countries have red+yellow before green STATE_GREEN, STATE_YELLOW } TrafficState; typedef enum { EVENT_TIMER, EVENT_EMERGENCY, EVENT_MANUAL_OVERRIDE } TrafficEvent; const char* stateToString(TrafficState state) { switch (state) { case STATE_RED: return "RED"; case STATE_RED_YELLOW: return "RED+YELLOW"; case STATE_GREEN: return "GREEN"; case STATE_YELLOW: return "YELLOW"; default: return "UNKNOWN"; } } TrafficState nextState(TrafficState current, TrafficEvent event) { switch (current) { case STATE_RED: if (event == EVENT_TIMER) return STATE_RED_YELLOW; break; case STATE_RED_YELLOW: if (event == EVENT_TIMER) return STATE_GREEN; break; case STATE_GREEN: if (event == EVENT_TIMER) return STATE_YELLOW; if (event == EVENT_EMERGENCY) return STATE_RED; break; case STATE_YELLOW: if (event == EVENT_TIMER) return STATE_RED; break; } // No transition return current; } int main() { TrafficState state = STATE_RED; printf("Starting traffic light simulation:\n"); // Simulate 10 timer events for (int i = 0; i < 10; i++) { printf("State: %s\n", stateToString(state)); state = nextState(state, EVENT_TIMER); // Simulate emergency at step 5 if (i == 5) { printf("EMERGENCY VEHICLE APPROACHING!\n"); state = nextState(state, EVENT_EMERGENCY); } } return 0; } Enums vs Macros vs const int
1. Comparison Example
#include <stdio.h> // Method 1: #define macros #define MONTH_JAN 1 #define MONTH_FEB 2 #define MONTH_MAR 3 // ... and so on // Method 2: const int const int JAN = 1; const int FEB = 2; const int MAR = 3; // Method 3: enum (recommended) typedef enum { JANUARY = 1, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER } Month; void printMonth(Month m) { switch (m) { case JANUARY: printf("January\n"); break; case FEBRUARY: printf("February\n"); break; case MARCH: printf("March\n"); break; // ... etc default: printf("Invalid month\n"); } } int main() { // With enum, we get type checking Month current = JULY; printMonth(current); // OK // This would generate a warning/error with proper compiler flags // Month invalid = 99; // Compiler may warn about implicit conversion // With #define, no type checking int month = MONTH_JUL; // No indication this is a month return 0; } Advantages of Enums:
- Type safety (with compiler warnings)
- Automatic value assignment
- Better debugging (symbol names in debugger)
- Scope control
- Can be used in switch statements
Disadvantages:
- No type safety in standard C (but can be improved with compiler flags)
- Size is implementation-dependent (usually int)
Scope and Namespace Considerations
1. Enum Scope
#include <stdio.h> // Global enum enum GlobalEnum { GLOBAL_A, GLOBAL_B }; void function() { // Local enum enum LocalEnum { LOCAL_X, LOCAL_Y }; enum LocalEnum e = LOCAL_X; printf("Local enum value: %d\n", e); } int main() { enum GlobalEnum g = GLOBAL_A; printf("Global enum value: %d\n", g); function(); // LOCAL_X is not accessible here - out of scope // enum LocalEnum invalid = LOCAL_X; // Error! return 0; } 2. Name Conflicts and Namespaces
#include <stdio.h> // C uses separate namespaces for tags and ordinary identifiers enum color { red, green, blue }; // This is allowed in C (unlike C++) int red = 5; // 'red' is in ordinary identifier namespace int main() { enum color c1 = red; // 'red' refers to enum constant int c2 = red; // 'red' refers to integer variable printf("Enum red = %d\n", c1); // 0 printf("Int red = %d\n", c2); // 5 // To avoid confusion, use typedef or naming conventions return 0; } Common Patterns and Best Practices
1. Enum for Error Handling
#include <stdio.h> typedef enum { ERR_SUCCESS = 0, ERR_NULL_POINTER = -1, ERR_INVALID_PARAM = -2, ERR_MEMORY = -3, ERR_FILE_NOT_FOUND = -4, ERR_PERMISSION_DENIED = -5, ERR_TIMEOUT = -6, ERR_NETWORK = -7 } ErrorCode; const char* errorToString(ErrorCode err) { switch (err) { case ERR_SUCCESS: return "Success"; case ERR_NULL_POINTER: return "Null pointer error"; case ERR_INVALID_PARAM: return "Invalid parameter"; case ERR_MEMORY: return "Memory allocation failed"; case ERR_FILE_NOT_FOUND: return "File not found"; case ERR_PERMISSION_DENIED: return "Permission denied"; case ERR_TIMEOUT: return "Operation timed out"; case ERR_NETWORK: return "Network error"; default: return "Unknown error"; } } ErrorCode processFile(const char* filename) { if (filename == NULL) { return ERR_NULL_POINTER; } FILE* file = fopen(filename, "r"); if (file == NULL) { return ERR_FILE_NOT_FOUND; } // Process file... fclose(file); return ERR_SUCCESS; } int main() { ErrorCode result = processFile("nonexistent.txt"); if (result != ERR_SUCCESS) { printf("Error: %s (code %d)\n", errorToString(result), result); } return 0; } 2. Enum with String Conversion
#include <stdio.h> typedef enum { LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR, LOG_FATAL } LogLevel; // Array mapping enum to strings const char* LOG_LEVEL_NAMES[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" }; // Ensure array size matches enum #define LOG_LEVEL_COUNT (sizeof(LOG_LEVEL_NAMES) / sizeof(LOG_LEVEL_NAMES[0])) // Compile-time check (C11 _Static_assert) _Static_assert(LOG_LEVEL_COUNT == 5, "Log level names array size mismatch"); void logMessage(LogLevel level, const char* message) { if (level >= 0 && level < LOG_LEVEL_COUNT) { printf("[%s] %s\n", LOG_LEVEL_NAMES[level], message); } else { printf("[UNKNOWN] %s\n", message); } } // Convert string to enum (case-sensitive) LogLevel stringToLogLevel(const char* name) { for (int i = 0; i < LOG_LEVEL_COUNT; i++) { if (strcmp(LOG_LEVEL_NAMES[i], name) == 0) { return (LogLevel)i; } } return -1; // Not found } int main() { logMessage(LOG_INFO, "Application started"); logMessage(LOG_WARNING, "Low memory"); logMessage(LOG_ERROR, "Failed to connect"); LogLevel level = stringToLogLevel("ERROR"); if (level != -1) { logMessage(level, "This is an error message"); } return 0; } 3. Enum Iteration
#include <stdio.h> typedef enum { OP_ADD, OP_SUBTRACT, OP_MULTIPLY, OP_DIVIDE, OP_MODULO, OP_COUNT // Special marker for count } Operation; int performOperation(Operation op, int a, int b) { switch (op) { case OP_ADD: return a + b; case OP_SUBTRACT: return a - b; case OP_MULTIPLY: return a * b; case OP_DIVIDE: return b != 0 ? a / b : 0; case OP_MODULO: return b != 0 ? a % b : 0; default: return 0; } } const char* operationToString(Operation op) { static const char* names[] = { "ADD", "SUBTRACT", "MULTIPLY", "DIVIDE", "MODULO" }; if (op >= 0 && op < OP_COUNT) { return names[op]; } return "UNKNOWN"; } int main() { int x = 10, y = 3; // Iterate over all operations for (Operation op = 0; op < OP_COUNT; op++) { int result = performOperation(op, x, y); printf("%d %s %d = %d\n", x, operationToString(op), y, result); } return 0; } 4. Enum with Flags Pattern
#include <stdio.h> #include <stdbool.h> typedef enum { STYLE_NONE = 0, STYLE_BOLD = 1 << 0, // 1 STYLE_ITALIC = 1 << 1, // 2 STYLE_UNDERLINE = 1 << 2, // 4 STYLE_STRIKE = 1 << 3, // 8 STYLE_SUPERSCRIPT = 1 << 4, // 16 STYLE_SUBSCRIPT = 1 << 5 // 32 } TextStyle; // Combine styles TextStyle styleCombine(TextStyle a, TextStyle b) { return a | b; } // Check if style has specific attribute bool styleHas(TextStyle style, TextStyle attribute) { return (style & attribute) == attribute; } // Remove attribute TextStyle styleRemove(TextStyle style, TextStyle attribute) { return style & ~attribute; } void printStyle(TextStyle style) { printf("Style: "); if (style == STYLE_NONE) { printf("NORMAL"); } else { if (style & STYLE_BOLD) printf("BOLD "); if (style & STYLE_ITALIC) printf("ITALIC "); if (style & STYLE_UNDERLINE) printf("UNDERLINE "); if (style & STYLE_STRIKE) printf("STRIKE "); if (style & STYLE_SUPERSCRIPT) printf("SUPERSCRIPT "); if (style & STYLE_SUBSCRIPT) printf("SUBSCRIPT "); } printf("\n"); } int main() { TextStyle myStyle = STYLE_BOLD | STYLE_ITALIC | STYLE_UNDERLINE; printStyle(myStyle); // BOLD ITALIC UNDERLINE printf("Has bold? %s\n", styleHas(myStyle, STYLE_BOLD) ? "Yes" : "No"); printf("Has strike? %s\n", styleHas(myStyle, STYLE_STRIKE) ? "Yes" : "No"); // Remove italic myStyle = styleRemove(myStyle, STYLE_ITALIC); printStyle(myStyle); // BOLD UNDERLINE return 0; } Advanced: Enum with Associated Data
While C enums cannot directly store associated data like in some languages, you can create parallel arrays:
#include <stdio.h> typedef enum { COLOR_RED, COLOR_GREEN, COLOR_BLUE, COLOR_YELLOW, COLOR_CYAN, COLOR_MAGENTA } Color; // Associated data structures typedef struct { int r, g, b; } RGB; const RGB COLOR_RGB[] = { {255, 0, 0}, // RED {0, 255, 0}, // GREEN {0, 0, 255}, // BLUE {255, 255, 0}, // YELLOW {0, 255, 255}, // CYAN {255, 0, 255} // MAGENTA }; const char* COLOR_NAMES[] = { "Red", "Green", "Blue", "Yellow", "Cyan", "Magenta" }; // Function to get RGB for color RGB getRGB(Color c) { if (c >= 0 && c < sizeof(COLOR_RGB) / sizeof(COLOR_RGB[0])) { return COLOR_RGB[c]; } return (RGB){0, 0, 0}; // Default black } int main() { Color myColor = COLOR_CYAN; RGB rgb = getRGB(myColor); printf("%s: RGB(%d, %d, %d)\n", COLOR_NAMES[myColor], rgb.r, rgb.g, rgb.b); return 0; } Compiler-Specific Features
1. GCC/Clang Attributes for Enums
#include <stdio.h> // Force enum to use unsigned int typedef enum __attribute__((packed)) { FLAG_A = 0, FLAG_B = 1, FLAG_C = 2 } PackedEnum; // Force enum to use specific size typedef enum __attribute__((__packed__)) { SMALL_A, SMALL_B, SMALL_C } __attribute__((__packed__)) SmallEnum; // Deprecate specific values typedef enum { OLD_VALUE __attribute__((deprecated)), NEW_VALUE } DeprecatedEnum; int main() { printf("Size of PackedEnum: %zu bytes\n", sizeof(PackedEnum)); printf("Size of SmallEnum: %zu bytes\n", sizeof(SmallEnum)); return 0; } 2. MSVC-Specific
#ifdef _MSC_VER // Force enum to use 1 byte #pragma pack(push, 1) typedef enum { MSVC_A, MSVC_B, MSVC_C } SmallEnumMSVC; #pragma pack(pop) // Force enum to be treated as int typedef enum { VALUE1, VALUE2 } StandardEnum; #endif Common Pitfalls and Solutions
1. Enum Size Assumptions
#include <stdio.h> #include <stdint.h> // DON'T assume enum size enum SomeEnum { ITEM1, ITEM2, ITEM3 }; // Better: Be explicit about expected range typedef enum { SAFE_ITEM1, SAFE_ITEM2, SAFE_ITEM3, SAFE_MAX } SafeEnum; // For large values, use explicit types typedef enum { BIG_VALUE = 0xFFFFFFFF, // May not fit in int on some platforms ANOTHER_BIG = 0x100000000 // Definitely won't fit in int } RiskyEnum; // Better: Use uint32_t for known ranges typedef enum { U32_VALUE1 = 0xFFFFFFFFu, U32_VALUE2 = 0xFFFFFFFEu } U32Enum; int main() { printf("Size of SomeEnum: %zu\n", sizeof(enum SomeEnum)); printf("Size of SafeEnum: %zu\n", sizeof(SafeEnum)); return 0; } 2. Type Safety Workarounds
#include <stdio.h> // Standard C has weak enum typing typedef enum { MONDAY, TUESDAY, WEDNESDAY } Day; typedef enum { JANUARY, FEBRUARY, MARCH } Month; // This compiles without warning in standard C void processDay(Day d) { printf("Day: %d\n", d); } // Workaround: Use struct wrapper for type safety typedef struct { enum { DAY_MONDAY, DAY_TUESDAY, DAY_WEDNESDAY } value; } SafeDay; typedef struct { enum { MONTH_JAN, MONTH_FEB, MONTH_MAR } value; } SafeMonth; void processSafeDay(SafeDay d) { printf("Safe day: %d\n", d.value); } int main() { // Unsafe - this compiles but is wrong processDay(FEBRUARY); // Month passed as Day! // Safe - won't compile with mismatched types SafeDay d = {DAY_MONDAY}; // SafeMonth m = {MONTH_JAN}; // processSafeDay(m); // Compiler error processSafeDay(d); // OK return 0; } Conclusion
Enumerations are a powerful feature in C that, when used properly, can significantly improve code readability, maintainability, and safety. They provide a way to group related constants, enable better self-documenting code, and facilitate safer programming patterns.
Best Practices Summary:
- Use enums for related constants instead of separate
#definemacros - Use typedef to create convenient type names
- Include a COUNT enumerator for iteration and bounds checking
- Use explicit values when the numeric values matter (e.g., for external interfaces)
- Consider bit flags for combinations of boolean options
- Create parallel arrays when enums need associated data
- Use compiler warnings (
-Wswitchin GCC) to catch missing enum cases in switches - Be consistent with naming conventions (e.g., UPPER_CASE or PascalCase)
Enums bridge the gap between primitive integers and higher-level abstractions, making C code more expressive while maintaining the performance characteristics of integer operations. Mastery of enums is essential for any serious C programmer.
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/
