I have a C macro that concatenates bits together in order to resolve to other macros. I'll demonstrate using an admittedly pointless macro called MULT
which multiplies two numbers. So long as I pass in an actual literal integer to its first parameter it works. But passing in a mathematical expression triggers an error.
For example:
#define MULT_2(X) X+X
#define MULT_3(X) X+X+X
#define MULT_4(X) X+X+X+X
#define EXPAND_(A) A
#define MULT__(N, X) EXPAND_(MULT_ ## N)(X)
#define MULT_(N, X) MULT__(N, X)
#define MULT(N, X) MULT_(EXPAND_(N), X)
int main() {
int num;
// This works:
num = MULT(4, 1);
printf("num: %d\n", num);
// This does not:
num = MULT(2+2, 1);
printf("num: %d\n", num);
return 0;
}
(To be honest, I don't fully understand why getting this macro to work with just a literal integer requires three extra macros, MULT_
, MULT__
, and EXPAND_
. But regardless...)
Is there anyway to rewrite this so that passing in an expression like 2+2
or 1 * 4
or 1 << 2
to its first argument will actually work?
I'm curious about the answer mainly to broaden my knowledge of C and its preprocessor. But I'm also hoping to make use of this for a project that's being written in C89, which means no variadic macros, so if there's a solution that avoids using those, I'd love to see it!
This is, for all intents and purposes, impossible. C macro token concatenation (##) does not evaluate expressions, it only merges tokens, as the name implies.
This is what the macro you've created expands to when trying to add a mathematical expression in:
#define MULT_2(X) X + X
#define MULT_3(X) X + X + X
#define MULT_4(X) X + X + X + X
#define EXPAND_(A) A
#define MULT__(N, X) EXPAND_(MULT_##N)(X)
#define MULT_(N, X) MULT__(N, X)
#define MULT(N, X) MULT_(EXPAND_(N), X)
// MULT(2+2, 1)
MULT_2 + 2(1)
This is obviously not the desired effect.