3 ms·
This is a neat hack, and very well written. I felt a bit of nostalgia looking at the (classical) cpp flex to avoid repeating an identifier #define X(s) #s
by enriquto 2y ago
This is a neat hack, and very well written. I felt a bit of nostalgia looking at the (classical) cpp flex to avoid repeating an identifier
#define X(s) #s
#define S(s) X(s)
- shawnz 2y agoFor the unfamiliar, what does this pattern do exactly?
- ahartmetz 2y agoIt turns a macro argument into a string of that argument. Let's say you have a mydebug(expression) macro that should print both "expression" and the value of expression.
- jjnoakes 2y agoThe macro X turns its argument into a string, but using it on its own means you can't turn other macro values into strings, only macro names. #define F 42 #define X(s) #s X(5) // Expands to "5" (as a string literal) X(F) // Expands to "F" not "42" If you add one level of recursive macro expansion, though, that expands the macro argument as well as the macro definition: #define F 42 #define X(s) #s #define S(s) X(s) S(5) // "5" as expected S(F) // "42" because S(F) expands to X(42) expands to "42"
- enriquto 2y agoIn that case it's just to convert the value of a macro into a string constant cat > a.c #define X(s) #s #define S(s) X(s) char *f(void) return { S(A); } ^D cc -E a.c char *f(void) return { "A"; } cc -DA=B -E a.c char *f(void) return { "B"; } More interestingly, you can use this trick to create code where some user-specified word appears as a string and as the name of the function. Exercice: write a macro M(x) such that compiling the code M(foo) M(bar) results in void print_foo(void) { puts("foo"); } voir print_bar(void) { puts("bar"); }
- delta_p_delta_x 2y ago> you can use this trick to create code where some user-specified word appears as a string and as the name of the function Ah, the poor man's introspection and reflection with C macros. shudder
- wruza 2y agoPrint an expression code to stdout using rich man’s introspection and reflection.