Swallowing comma in variadic macros on compilers that do not recognise ## - c

I need to write a variadic macro in C which must take zero or more arguments.
In gcc, that can be achieved by adding "##" after the comma, e.g. ,##____VA_ARGS____ as answered in Variadic macros with zero arguments.
However, the compiler in my build system (beyond my control) does not understand the ,## syntax and so does not swallow the comma.
Is there a workaround I can use?

Yes, gcc swallowing the comma is non standard and you should not rely on that.
With C99 conforming preprocessors you may achieve a similar effect by testing for a macro arguments that is the empty token. For the ideas of how this works you could see here, for a whole set of preprocessor macros that ease the programming of such features there is P99.

Using a simplified version what Jens spelled out, a possible approach is described below.
E_ is used to inject an argument, while I_ is used to cause indirect invocation of a macro. V_ is required to add an additional level of indirection, which seems required for some compilers.
#define V_(...) __VA_ARGS__
#define I_(M,...) V_(M(__VA_ARGS__))
#define E_() _,
Now, suppose you need a macro MAC to handle 0, 1, or 2 arguments:
MAC(1, 2);
MAC(1);
MAC();
One possible implementation might look like:
#define MAC_X(_2,_1,X,...) MAC_##X
#define MAC(...) V_(V_(MAC_X(__VA_ARGS__,2,_))(__VA_ARGS__))
#define MAC_2(...) function_for_2(__VA_ARGS__)
#define MAC_1(...) function_for_1(__VA_ARGS__)
#define MAC_0(...) function_for_0(__VA_ARGS__)
#define MAC_Y(_1,Y,...) MAC_##Y
#define MAC__(...) I_(MAC_Y, E_ __VA_ARGS__ () 0, 1)(__VA_ARGS__)
And expanding it to 3 arguments is relatively straightforward. The only messiness is detecting 1 or 0 arguments, which does not change:
-#define MAC_X(_2,_1,X,...) MAC_##X
-#define MAC(...) V_(V_(MAC_X(__VA_ARGS__,2,_))(__VA_ARGS__))
+#define MAC_X(_3,_2,_1,X,...) MAC_##X
+#define MAC(...) V_(V_(MAC_X(__VA_ARGS__,3,2,_))(__VA_ARGS__))
+#define MAC_3(...) function_for_3(__VA_ARGS__)
#define MAC_2(...) function_for_2(__VA_ARGS__)
For more than 1 argument, the MAC macro expands into MAC_2 (or MAC_3). But, for 1 or 0 arguments, the MAC macro expands to MAC__.
The MAC__ macro applies Jens' trick to detect whether it was passed 1 or 0 arguments. It does this with the E_ helper macro, and injecting its argument between E_ and the () that would cause it to be invoked. If there are 0 arguments, the E_ is invoked, and an argument is injected. The injected argument causes 0 to be the second argument for MAC_Y to select. If there is 1 argument, E_ is not expanded. The first argument to the to MAC_Y becomes E_ ... () 0 (where the ... is whatever the first argument was), and the second argument for MAC_Y is 1. This allows MAC_Y to invoke either MAC_0 or MAC_1.

Related

Generalized iteration over arguments of macro in the C preprocessor

There were several questions here regarding variadic macros in C. These include:
How to make a variadic macro (variable number of arguments) which explains the basics, e.g., passing a variable number of arguments to functions such as printf
Is it possible to iterate over arguments in variadic macros?, which explains how to iteratively apply a macro to each of the arguments of the variadic macro.
https://github.com/swansontec/map-macro which explains how to do so on pairs
My question is related to the iteration technique. I am interested in a macro with this generalized semantics.
ITERATE(Before, Action, Between, After, Empty, ...)
that will place Before prior to all expansions, apply Action to each argument, place Between between every two consecutive applications, and will finally place the expansion of After. Moreover, if the number of argument With such a macro, it should be possible to write
// Loop elements
#define A(x) (x)
#define Befor (
#define After )
#define Between ||
#define Empty 1
// Define an OR macro
#define OR(...) ITERATE(Before, A, Between, Empty, __VA_ARGS__)
// Use it
OR() // Expands to 1
OR(a) // Expands to ((a))
OR(a,b) // Expands to ((a)||(b))
OR(a,b,c) // Expands to to ((a)||(b)||(c))
The purpose of course is not to write an OR function. A generalized functionality could be for more intricate applications. E.g., a macro for defining classes and functions, something to print the trace, etc.
I never liked the recursive REPEAT() macro idiom - it generates horrible hour long read error messages that are.. recursive, so you don't know where the error is and it's also hard to grasp how the OBSTRUCT(REPEAT_INDIRECT) () stuff works. Overall, overloading the macro on number of arguments and using an external tool (shell script or m4 preprocessor) to generate C source code is waay easier, easier to read, maintain and fix and also you can expand the macros on the tools side removing the burden of recursive expansion on C side. With that in mind, your ITERATE can be generated with existing preprocessor libraries, P99_FOR or BOOST_FOREACH comes to mind.
Also, typing shift all the time is strange - I prefer snake case. Here's a reduced example without Before and After macros with overloading the macro on number of arguments:
#define _in_ITERATE_0(f,b,e) e()
#define _in_ITERATE_1(f,b,e,_1) f(_1)
#define _in_ITERATE_2(f,b,e,_1,...) f(_1)b()_in_ITERATE_1(f,b,e,__VA_ARGS__)
#define _in_ITERATE_3(f,b,e,_1,...) f(_1)b()_in_ITERATE_2(f,b,e,__VA_ARGS__)
// or you could expand it instead of reusing previous one with same result:
#define _in_ITERATE_4(f,b,e,_1,_2,_3,_4) f(_1)b()f(_2)b()f(_3)b()f(_4)
// etc.... generate
#define _in_ITERATE_N(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,N,...) _in_ITERATE_##N
#define ITERATE(func, between, empty, ...) \
_in_ITERATE_N(0,##__VA_ARGS__,9,8,7,6,5,4,3,2,1,0)(func, between, empty, ##__VA_ARGS__)
#define _in_OR_OP(x) (x)
#define _in_OR_EMPTY() 1
#define _in_OR_BETWEEN() ||
#define OR(...) (ITERATE(_in_OR_OP, _in_OR_BETWEEN, _in_OR_EMPTY, ##__VA_ARGS__))
// Use it
OR() // Expands to (1)
OR(a) // Expands to ((a))
OR(a,b) // Expands to ((a)||(b))
OR(a,b,c) // Expands to to ((a)||(b)||(c))
outputs:
(1)
((a))
((a)||(b))
((a)||(b)||(c))
For more examples on overloading macro on count of arguments see this thread. I am using ## GNU extension to remove the comma before __VA_ARGS__ because I am used to using it - I think __VA_OPT__(,) should be nowadays preferred, I am not sure.

Conditional Preprocessor macro expansion in C

I have a macro, SOME_MACRO. It takes an argument.
Definition of SOME_MACRO:
#define SOME_MACRO(arg) __SOME_MACRO(arg)
Further I want __SOME_MACRO(arg) to expand to "ABC" if arg is 0. And if arg is not zero, __SOME_MACRO(arg) should expand to "DEF"
Suppose I call with argument 0, that is: SOME_MACRO(0)
I need to test at preprocessing time, whether the argument is zero or not.
#if <argument is zero> // line 1
#define __SOME_MACRO(arg) "ABC"
#elif
#define __SOME_MACRO(arg) "DEF"
#endif
My question is: What should be at line 1?
Taking an example:
SOME_MACRO(2) should expand to "DEF"
SOME_MACRO(0) should expand to "ABC"
Here is a solution for the requested behavior. Do not use it, it is bad practice, and you should not be attempting this.
/* Define __SOME_MACRO:
Defer is used so that its arguments will be macro-replaced before
Kludge is processed.
"Kludge" is pasted to arg. If this makes "Kludge0", it will be
replaced by two arguments (an empty argument, a comma, and the argument
"abc"). Otherwise, if it forms a single token, that is one argument.
(If the pasting does not form a proper token, the behavior is
undefined. Most likely, the compiler will report an error.)
The resulting argument(s) are then passed to Kludge, followed by "DEF".
Kludge is replaced by its second argument. If __SOME_MACRO's argument
was "0", this second argument is "ABC". Otherwise, it is "DEF".
*/
#define Kludge0 , "ABC"
#define Kludge(x, y,...) y
#define Defer(x, ...) Kludge(x, __VA_ARGS__)
#define __SOME_MACRO(arg) Defer(Kludge##arg, "DEF",)
__SOME_MACRO(0)
__SOME_MACRO(2)
This is not possible. The expression given to #if is only evaluated once, at the line where #if is encountered. There is no way to have it evaluated again each time you invoke your macro.
As Eric Postpischil says, C does not have any general way to make the expansion of a macro conditional on its arguments.
A couple of possible alternatives:
Use an expression with the ternary ?: operator, as pmg suggested in a comment:
#define __SOME_MACRO(arg) ((arg) ? "DEF" : "ABC")
Then SOME_MACRO(0) will expand to ((0) ? "DEF" : "ABC"). Any reasonable compiler will notice that the condition is a constant, and compile this just as if you had only written "ABC"; it should not generate code for a test nor for the unreachable branch. Conditionals with the ternary operator can even be used in expressions that must be compile-time constants, as long as the condition is itself a compile-time constant; e.g. __SOME_MACRO(0) can be used to initialize a global or static variable.
Of course this will not work if the desired expansion is not syntactically an expression, e.g. if you are trying to use your macro to create declarations or definitions or something more syntactically elaborate.
If you know that only a small set of possible arguments will be used, you could use token pasting with the ## operator to expand the macro as one of another set of macros:
#define __SOME_MACRO_0 "ABC"
#define __SOME_MACRO_1 "DEF"
#define __SOME_MACRO_2 "DEF"
#define __SOME_MACRO(arg) __SOME_MACRO_ ## arg
Then __SOME_MACRO(0) expands to "ABC" and __SOME_MACRO(2) expands to "DEF". However __SOME_MACRO(3) will not compile unless you write a corresponding __SOME_MACRO_3 macro, and __SOME_MACRO(0+1) cannot be made to work at all, at least not in any way that I know of.
(As written, __SOME_MACRO(0+1) expands to "ABC"+1, which is equivalent to "BC" and will probably cause you a lot of confusion before you figure out what is wrong. __SOME_MACRO(1-1) is even worse...)
Also, #define ZERO 0 followed by __SOME_MACRO(ZERO) doesn't work as it stands, thought it can be fixed by doing
#define SECOND_MACRO(arg) __SOME_MACRO_ # arg
#define __SOME_MACRO(arg) SECOND_MACRO(arg)

Surprising expansion of variadic GNU C preprocessor macros in the presence of the ## operator

If we define a macro
#define M(x, ...) { x, __VA_ARGS__ }
and then use it passing itself as an argument
M(M(1, 2), M(3, 4), M(5, 6))
then it expands to the expected form:
{ { 1, 2 }, { 3, 4 }, { 5, 6 } }
However, when we use the ## operator (to prevent dangling comma from appearing in the output in the case of the single argument invocations, as documented in the GCC manual), i.e.
#define M0(x, ...) { x, ## __VA_ARGS__ }
then the expansion of arguments in
M0(M0(1,2), M0(3,4), M0(5,6))
seems to stop after the first argument, i.e. we get:
{ { 1,2 }, M0(3,4), M0(5,6) }
Is this behavior a bug, or does it stem from some principle?
(I have also checked it with clang, and it behaves in the same way as GCC)
Way down at the end of this answer there is a possible solution.
Is this behavior a bug, or does it stem from some principle?
It stems from two principles whose interaction is pretty subtle. So I agree that it is surprising, but it's not a bug.
The two principles are the following:
Inside the replacement of macro invocation, that macro is not expanded. (See the GCC Manual Section 3.10.5, Self-Referential Macros or the C Standard, §6.10.3.4 paragraph 2.) This precludes recursive macro expansion, which in most cases would produce infinite recursion if allowed. Although it is likely that no-one anticipated such uses, it turns out that there would be ways of using recursive macro expansion which would not result in infinite recursion (see the Boost Preprocessor Library documentation for a thorough discussion of this issue), but the standard isn't going to get changed now.
If ## is applied to a macro argument, it suppresses macro expansion of that argument. (See the GCC Manual section 3.5, Concatenation or the C Standard, §6.10.3.3 paragraph 2.) The suppression of expansion is part of the C Standard, but GCC/Clang's extension to allow use of ## to conditionally suppress the comma preceding __VA_ARGS__ is non-standard. (See the GCC Manual Section 3.6, Variadic Macros.) Apparently, the extension still respects the standard's rule about not expanding concatenated macro arguments.
Now, the curious thing about the second point, with respect to optional comma suppression, is that you hardly ever notice it in practice. You can use ## to conditionally suppress commas and arguments will still get expanded as normal:
#define SHOW_ARGS(arg1, ...) Arguments are (arg1, ##__VA_ARGS__)
#define DOUBLE(a) (2 * a)
SHOW_ARGS(DOUBLE(2))
SHOW_ARGS(DOUBLE(2), DOUBLE(3))
This expands to:
Arguments are ((2 * 2))
Arguments are ((2 * 2), (2 * 3))
Both DOUBLE(2) and DOUBLE(3) are expanded normally, despite the fact that one of them is an argument to the concatenation operator.
But there's a subtlety to macro expansion. Expansion happens twice:
First, macro arguments are expanded. (This expansion is in the context of the text which invokes the macro.) These expanded arguments are substituted for the parameters in the macro replacement body (but only where the parameter is not an argument to # or ##).
Then the # and ## operators are applied to the replacement token list.
Finally, the resulting replacement tokens are inserted into the input stream, so that they are expanded again. This time, the expansion is in the context of the macro so recursive invocation is suppressed.
With that in mind, we see that in SHOW_ARGS(DOUBLE(2), DOUBLE(3)), DOUBLE(2) is expanded in step 1, before being inserted into the replacement token list, and DOUBLE(3) is expanded in step 3, as part of the replacement token list.
This doesn't make a difference with DOUBLE inside SHOW_ARGS, since they're different macros. But the difference would become apparent if they were the same macro.
To see the difference, consider the following macro:
#define INVOKE(A, ...) A(__VA_ARGS__)
That macro creates a macro invocation (or a function invocation, but here we're only interested in the case where it's a macro). That is, in turns INVOKE(X, Y) into X(Y). (That's a simplification of a useful feature, where the named macro is actually invoked several times, possibly with slightly different arguments.)
That works fine with SHOW_ARGS:
INVOKE(SHOW_ARGS, one arg)
⇒ Arguments are (one arg)
But if we try to INVOKE the macro INVOKE itself, we find that the ban on recursive invocation takes effect:
INVOKE(INVOKE, SHOW_ARGS, one arg)
⇒ INVOKE(SHOW_ARGS, one arg)
"Of course", we could expand INVOKE as an argument to INVOKE:
INVOKE(SHOW_ARGS, INVOKE(SHOW_ARGS, one arg))
⇒ Arguments are (Arguments are (one arg))
That works fine because there is no ## inside INVOKE, so expansion of the argument is not suppressed. But if the expansion of the argument had been suppressed, then the argument would be inserted into the macro body unexpanded, and then it would become a recursive expansion.
So that's what is going on in your example:
#define M0(x, ...) { x, ## __VA_ARGS__ }
M0(M0(1,2), M0(3,4), M0(5,6))
⇒ { { 1,2 }, M0(3,4), M0(5,6) }
Here, the first argument to the outer M0, M0(1,2), is not used with ##, so it is expanded as part of the invocation. The other two arguments are part of __VA_ARGS__, which is used with ##. Consequently, they are not expanded prior to being substituted into the macro's replacement list. But as part of the macro's replacement list, their expansion is suppressed by the no-recursive-macros rule.
You can easily work around that by defining two versions of the M0 macro, with the same contents but different names (as suggested in a comment to the OP):
#define M0(x, ...) { x, ## __VA_ARGS__ }
M0(M1(1,2), M1(3,4), M1(5,6))
⇒ { { 1,2 }, { 3,4 }, { 5,6 } }
But that's not very pleasant.
Solution: Use __VA_OPT__
C++2a will include a new feature designed specifically to assist with suppressing commas in variadic invocations: the __VA_OPT__ function-like macro. Inside a variadic macro expansion, __VA_OPT__(x) expands to its argument provided that there is at least one token in the variadic arguments. But if __VA_ARGS__ expands to an empty token list, so does __VA_OPT__(x). Thus, __VA_OPT__(,) can be used for conditional suppression of a comma just like the GCC ## extension, but unlike ##, it does not trigger suppression of macro expansion.
As an extension to the C standard, recent versions of GCC and Clang implement __VA_OPT__ for C as well as C++. (See the GCC Manual Section 3.6, Variadic Macros.) So if you're willing to rely on relatively recent compiler versions, there is a very clean solution:
#define M0(x, ...) { x __VA_OPT__(,) __VA_ARGS__ }
M0(M0(1,2), M0(3,4), M0(5,6))
⇒ { { 1 , 2 } , { 3 , 4 }, { 5 , 6 } }
Notes:
You can see these examples on Godbolt
This question was originally closed as a duplicate of Variadic macros: expansion of pasted tokens but I don't think that answer is really adequate to this particular situation.

Is there a way to force C preprocessor to evaluate macro arguments before the macro

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?
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.
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

Macro Meta Programming

I know this is probably either bad or impossible, but since this isn't a recursive macro I think it should be possible.
#define FOO 15
#define MAKE_BAR(x) BAR_##x
#define MY_FOO_BAR MAKE_BAR(FOO)
I'd like MY_FOO_BAR to evaluate to BAR_15. Is there a way to tell the preprocessor to evaluate FOO before passing it into MAKE_BAR?
You need another level of macro calls:
#define FOO 15
#define MAKE_BAR_INNER(x) BAR_##x
#define MAKE_BAR(x) MAKE_BAR_INNER(x)
#define MY_FOO_BAR MAKE_BAR(FOO)
This is because of how parameters are handled during functional macro expansion. The ## concatenation operator prevents parameter expansion, so you must "force" expansion by adding another "layer".

Resources