Skip to content

Instantly share code, notes, and snippets.

@r-lyeh
Last active August 11, 2025 08:31
Show Gist options
  • Save r-lyeh/fc51881d47c5cdac23ca914c79c6d7ff to your computer and use it in GitHub Desktop.
Save r-lyeh/fc51881d47c5cdac23ca914c79c6d7ff to your computer and use it in GitHub Desktop.
// [src] https://www.scs.stanford.edu/~dm/blog/va-opt.html
//
// gcc enum.c
// clang enum.c
// cl enum.c /Zc:preprocessor
#define PARENS ()
// Rescan macro tokens 256 times
#define EXPAND(arg) EXPAND1(EXPAND1(EXPAND1(EXPAND1(arg))))
#define EXPAND1(arg) EXPAND2(EXPAND2(EXPAND2(EXPAND2(arg))))
#define EXPAND2(arg) EXPAND3(EXPAND3(EXPAND3(EXPAND3(arg))))
#define EXPAND3(arg) EXPAND4(EXPAND4(EXPAND4(EXPAND4(arg))))
#define EXPAND4(arg) arg
#define FOR_EACH(macro, ...) \
__VA_OPT__(EXPAND(FOR_EACH_HELPER(macro, __VA_ARGS__)))
#define FOR_EACH_HELPER(macro, a1, ...) \
macro(a1) \
__VA_OPT__(FOR_EACH_AGAIN PARENS (macro, __VA_ARGS__))
#define FOR_EACH_AGAIN() FOR_EACH_HELPER
#define ENUM_CASE(name) case name: return #name;
#define MAKE_ENUM(type, typestr, ...) \
typedef enum type { __VA_ARGS__ } type; \
const char *typestr(type _e) { \
switch (_e) { default: return ""; \
FOR_EACH(ENUM_CASE, __VA_ARGS__) }}
MAKE_ENUM(MyType, MyTypeStr, ZERO, ONE, TWO, THREE);
#include <stdio.h>
void test(MyType e) {
printf("%s=%d\n", MyTypeStr(e), e);
}
int main() {
test(ZERO);
test(ONE);
test(TWO);
test(THREE);
}
/*
ZERO=0
ONE=1
TWO=2
THREE=3
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment