Skip to content

Instantly share code, notes, and snippets.

@nilput
Last active July 17, 2021 06:46
Show Gist options
  • Select an option

  • Save nilput/8c498f05d49287b27615090b77ea1a1e to your computer and use it in GitHub Desktop.

Select an option

Save nilput/8c498f05d49287b27615090b77ea1a1e to your computer and use it in GitHub Desktop.
C Constants Definitions, Preprocessor Macro Function Redefinition Example
/*
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