问题
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.
回答1:
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;
}
回答2:
You have to put the ...
at the end, but using LAST
and POP_LAST
macros, you can keep the same order of arguments for your macro and define it like this:
#define M(obj,met, ...) obj##_##met(const void * self, POP_LAST(__VA_ARGS__)) { \
LAST(__VA_ARGS__) \
}
Heres how you can define these macros:
/* This counts the number of args */
#define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N
#define NARGS(...) NARGS_SEQ(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
/* This will let macros expand before concating them */
#define PRIMITIVE_CAT(x, y) x ## y
#define CAT(x, y) PRIMITIVE_CAT(x, y)
/* This will pop the last argument off */
#define POP_LAST(...) CAT(POP_LAST_, NARGS(__VA_ARGS__))(__VA_ARGS__)
#define POP_LAST_1(x1)
#define POP_LAST_2(x1, x2) x1
#define POP_LAST_3(x1, x2, x3) x1, x2
#define POP_LAST_4(x1, x2, x3, x4) x1, x2, x3
#define POP_LAST_5(x1, x2, x3, x4, x5) x1, x2, x3, x4
#define POP_LAST_6(x1, x2, x3, x4, x5, x6) x1, x2, x3, x4, x5
#define POP_LAST_7(x1, x2, x3, x4, x5, x6, x7) x1, x2, x3, x4, x5, x6
#define POP_LAST_8(x1, x2, x3, x4, x5, x6, x7, x8) x1, x2, x3, x4, x5, x6, x7
/* This will return the last argument */
#define LAST(...) CAT(LAST_, NARGS(__VA_ARGS__))(__VA_ARGS__)
#define LAST_1(x1) x1
#define LAST_2(x1, x2) x2
#define LAST_3(x1, x2, x3) x3
#define LAST_4(x1, x2, x3, x4) x4
#define LAST_5(x1, x2, x3, x4, x5) x5
#define LAST_6(x1, x2, x3, x4, x5, x6) x6
#define LAST_7(x1, x2, x3, x4, x5, x6, x7) x7
#define LAST_8(x1, x2, x3, x4, x5, x6, x7, x8) x8
These macros will work for up to 8 arguments. You can easily extend them to handle more if you like.
来源:https://stackoverflow.com/questions/3850421/can-i-define-variadic-c-preprocessor-macros-with-va-args-in-the-middle-instead