Last active
July 17, 2021 06:46
-
-
Save nilput/8c498f05d49287b27615090b77ea1a1e to your computer and use it in GitHub Desktop.
C Constants Definitions, Preprocessor Macro Function Redefinition Example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| In many cases, we have situations where we need to define a lot of constants / data definitions. | |
| examples: enums, definitions such as cpu instructions encodings, http message response types, lookup tables, etc.. | |
| this method is seen in many projects and it's a good solution to the problem, it avoid redundancy and code duplication, | |
| and it help maintain a single source of truth. | |
| */ | |
| #include <stdio.h> | |
| enum item_type { FRUIT, VEGETABLE }; | |
| struct item_def { | |
| const char *str; | |
| size_t len; | |
| enum item_type typ; | |
| }; | |
| // This macro expands to nothing | |
| #define LIST_ENTRY(str, len, type) | |
| // Note with C preprocessor a trailing backslash \ continues the line. | |
| #define LIST \ | |
| LIST_ENTRY("Apple", 5, FRUIT) \ | |
| LIST_ENTRY("Orange", 6, FRUIT) \ | |
| LIST_ENTRY("Corn", 4, VEGETABLE) \ | |
| LIST_ENTRY("Cucumber", 8, VEGETABLE) \ | |
| LIST_ENTRY("Carrot", 6, VEGETABLE) \ | |
| LIST_ENTRY("Strawberry", 10, FRUIT) | |
| struct item_def definitions[] = { | |
| #undef LIST_ENTRY | |
| //Here this macro expands to initialize each struct item in the array we're definining. | |
| #define LIST_ENTRY(str, str_len, typ) {str, str_len, typ}, | |
| LIST | |
| }; | |
| //The following expression Can be derived as a constant (sizeof is an operator, not a function) | |
| const static size_t definitions_count = sizeof definitions / | |
| sizeof definitions[0]; | |
| // Here suppose we want to initialize another datatype or some kind of lookup table, we can just redefine the original | |
| // macro, without repeating/modifying the list. | |
| const static char *item_strings[] = { | |
| //Here we take the string argument and ignore the rest | |
| #undef LIST_ENTRY | |
| #define LIST_ENTRY(str, _, __) str, | |
| LIST | |
| }; | |
| const char *item_type(enum item_type typ) { | |
| struct { int typ; char *str; } defs[] = { | |
| {FRUIT, "FRUIT"}, | |
| {VEGETABLE, "VEGETABLE"}, | |
| }; | |
| for (int i = 0; i < sizeof defs / sizeof defs[0]; i++) | |
| if (typ == defs[i].typ) return defs[i].str; | |
| return "UNKNOWN"; | |
| } | |
| int main(void) { | |
| printf("Definitions: \n"); | |
| struct item_def *defs = definitions; | |
| for (size_t i = 0; i < definitions_count; i++) | |
| printf("{\"%s\", %zu, %s},\n", defs[i].str, defs[i].len, item_type(defs[i].typ)); | |
| printf("Item strings: "); | |
| for (size_t i = 0; i < sizeof item_strings / sizeof item_strings[0]; i++) | |
| printf("%s'%s'", i > 0 ? ", " : "", item_strings[i]); | |
| printf("\n"); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment