9
votes

I have a number of macros in the form

#define F(A,B)   Some function of A and B

and for readability I would like to define arguments for these macros e.g.

#define C A,B

so that I can say

F(C)

but the preprocessor tries to expand F before C and complains that F needs 2 arguments. Is there a way to make it expand C before it expands F so that the error does not occur?

2
Oh my god you should never do this.user1717828
I do not understand some peoples obsession with the pre-processor. Just use it for simple stuff. The compiler is a lot better - it has the luxury of type safety for startersEd Heal
If you need that, generate your C code from something else. Perhaps use some other preprocessor (e.g. m4 or gpp); it is not a job the the standard C preprocessorBasile Starynkevitch
@EdHeal Yeah, I agree. I even avoid non-macro variadic functions. Couldn't resist not to answer though.2501
lol 'for readability' in a macro question:)Martin James

2 Answers

11
votes

You can use an intermediate macro that takes a variable number of arguments:

#define F1(A,B) 
#define F(...) F1(__VA_ARGS__)

#define C A,B

int main(void) {
    F(C)
    F(1,2)
    return 0;
}

This should compile. You will still get a compilation failure if you pass more or less than two arguments, or arguments that don't expand to exactly two arguments.

0
votes

Macro expansion (erroneously) does not trigger argument recount. Therefore, any time macro expansion of a function invocation results in a different number of arguments, it must be forced to recount the number of arguments.

Use this pattern to force expansion and recount before invocation:

//Step 1: wrap the entire affected argument pack in parenthesis
#define mFn(A, ExpandingArgument) mFn1((A, ExpandingArgument))

//Step 2: intermediary layer without ## or # is required to actually expand
#define mFn1(...) mFn2(__VA_ARGS__)

//Step3: Paste the parenthesized arguments to final function identifier to trigger 
//       function like macro interpretation and invocation
#define mFn2(...) mFn3##__VA_ARGS__

//Step4: Implement the actual function as if the standard were written correctly
#define mFn3(A,B,C,...) //Do things