我可以在中间而不是末尾定义可变 C 预处理器宏吗?

发布于 2024-09-26 13:22:36 字数 480 浏览 9 评论 0原文

如果我这样做,GCC 会抱怨:

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

给我两个原因:

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

显然,C99 风格的可变参数宏期望在省略号之后立即使用右括号,实际上要求可变参数列表是宏的最后一个参数。我需要它位于中间才能生成上面宏中描述的速记符号。 GCC 是否支持此功能,使用另一种(非 C99)可变参数宏样式?我可以用其他方式模仿它吗?我不希望最后有可变参数列表,它会让我的符号变得混乱。而且我只能使用GCC。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

腻橙味 2024-10-03 13:22:36

不,你不能。 ... 必须出现在末尾。

但是您可以将 M 定义为

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

并将其用作

void M(foo, bar, int x, char y, double z) {
   content;
}

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;
}
云仙小弟 2024-10-03 13:22:36

您必须将 ... 放在末尾,但是使用 LASTPOP_LAST 宏,您可以为您的宏并按如下方式定义它:

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

以下是定义这些宏的方法:

/* 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

这些宏最多适用于 8 个参数。如果您愿意,您可以轻松扩展它们以处理更多内容。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文