Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I define variadic C preprocessor macros with __VA_ARGS in the middle instead of the end?

GCC complains if I do this:

#define M(obj,met, ..., contents) obj##_##met(const void * self, __VA_ARGS__) { \
   contents \
   }

Giving me these 2 reasons:

error: missing ')' in macro parameter list
warning: __VA_ARGS__ can only appear in the expansion of a C99 variadic macro

Apparently, C99 - style variadic macros expect the closing parenthesis immediately after the ellipsis, effectively demanding that the variadic list be the last arguments of the macro. I need it to be in the middle to produce my shorthand notation described in the above macro. Does GCC support this feature, using another (non-C99) variadic macro style? Can I emulate it doing it someway else? I don't want the variadic list at the end, it will make my notation confusing. And I can only use GCC.

like image 226
salvador p Avatar asked Oct 03 '10 15:10

salvador p


People also ask

Where is __ Va_args __ defined?

The C standard mandates that the only place the identifier __VA_ARGS__ can appear is in the replacement list of a variadic macro. It may not be used as a macro name, macro argument name, or within a different type of macro. It may also be forbidden in open text; the standard is ambiguous.

What is #__ Va_args __?

Preprocessor: __VA_ARGS__ : count arguments This is an attempt to define a few variadic macros that can be used to count the number of arguments given.

What is __ Va_opt __?

__VA_OPT__ is a new feature of variadic macros in C++20. It lets you optionally insert tokens depending on if a variadic macro is invoked with additional arguments. An example usage is comma elision in a standardized manner.

What is ## in C macro?

The double-number-sign or token-pasting operator (##), which is sometimes called the merging or combining operator, is used in both object-like and function-like macros. It permits separate tokens to be joined into a single token, and therefore, can't be the first or last token in the macro definition.


1 Answers

No you can't. The ... must appear at the end.

But you could define M as

#define M(obj,met, ...) obj##_##met(const void * self, __VA_ARGS__)

and use it as

void M(foo, bar, int x, char y, double z) {
   content;
}
like image 61
kennytm Avatar answered Sep 25 '22 11:09

kennytm