C 宏:如何将另一个宏映射到可变参数?

编程入门 行业动态 更新时间:2024-10-09 11:23:52
本文介绍了C 宏:如何将另一个宏映射到可变参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我想知道如何将一元函数(或另一个宏)应用于宏的可变参数,例如

I'd like to know how to apply a unary function (or another macro) to variadic arguments of a macro, like

int f(int a); #define apply(args...) <the magic> apply(a, b, c)

展开

f(a) f(b) f(c)

请注意,参数的数量是未知的.

Note that the number of arguments is unknown.

推荐答案

下面的代码适用于您所要求的最多 1024 个参数,并且没有使用诸如 boost 之类的其他东西.它定义了一个 EVAL(...) 和一个 MAP(m, first, ...) 宏来进行递归并在每次迭代中使用宏 m 与下一个参数 first.

The code below is working for what you've asked for with up to 1024 arguments and without using additional stuff like boost. It defines an EVAL(...) and also a MAP(m, first, ...) macro to do recursion and to use for each iteration the macro m with the next parameter first.

使用它,您的 apply(...) 看起来像:#define apply(...) EVAL(MAP(apply_, __VA_ARGS__)).

With the use of that, your apply(...) looks like: #define apply(...) EVAL(MAP(apply_, __VA_ARGS__)).

它主要是从 C Pre-Processor Magic 复制而来的.那里也有很好的解释.您还可以在 EVAL(...)rel="nofollow noreferrer">git repository,实际代码中也有很多解释.它是可变参数,所以它需要你想要的参数数量.

It is mostly copied from C Pre-Processor Magic. It is also great explained there. You can also download these helper macros like EVAL(...) at this git repository, there are also a lot of explanation in the actual code. It is variadic so it takes the number of arguments you want.

但我更改了 FIRST 和 SECOND 宏,因为它使用 Gnu 扩展,就像它在我复制它的源中一样.@HWalters 在下面的评论中说:

But I changed the FIRST and the SECOND macro as it uses a Gnu extension like it is in the source I've copied it from. This is said in the comments below by @HWalters:

具体来说,6.10.3p4:否则 [标识符列表以 ... 结尾] 调用中的参数应多于宏定义中的参数(不包括 ...)".

Specifically, 6.10.3p4: "Otherwise [the identifier-list ends in a ...] there shall be more arguments in the invocation than there are parameters in the macro definition (excluding the ...)".

主要功能部分:

int main() { int a, b, c; apply(a, b, c) /* Expands to: f(a); f(b); f(c); */ return 0; }

宏定义:

#define FIRST_(a, ...) a #define SECOND_(a, b, ...) b #define FIRST(...) FIRST_(__VA_ARGS__,) #define SECOND(...) SECOND_(__VA_ARGS__,) #define EMPTY() #define EVAL(...) EVAL1024(__VA_ARGS__) #define EVAL1024(...) EVAL512(EVAL512(__VA_ARGS__)) #define EVAL512(...) EVAL256(EVAL256(__VA_ARGS__)) #define EVAL256(...) EVAL128(EVAL128(__VA_ARGS__)) #define EVAL128(...) EVAL64(EVAL64(__VA_ARGS__)) #define EVAL64(...) EVAL32(EVAL32(__VA_ARGS__)) #define EVAL32(...) EVAL16(EVAL16(__VA_ARGS__)) #define EVAL16(...) EVAL8(EVAL8(__VA_ARGS__)) #define EVAL8(...) EVAL4(EVAL4(__VA_ARGS__)) #define EVAL4(...) EVAL2(EVAL2(__VA_ARGS__)) #define EVAL2(...) EVAL1(EVAL1(__VA_ARGS__)) #define EVAL1(...) __VA_ARGS__ #define DEFER1(m) m EMPTY() #define DEFER2(m) m EMPTY EMPTY()() #define IS_PROBE(...) SECOND(__VA_ARGS__, 0) #define PROBE() ~, 1 #define CAT(a,b) a ## b #define NOT(x) IS_PROBE(CAT(_NOT_, x)) #define _NOT_0 PROBE() #define BOOL(x) NOT(NOT(x)) #define IF_ELSE(condition) _IF_ELSE(BOOL(condition)) #define _IF_ELSE(condition) CAT(_IF_, condition) #define _IF_1(...) __VA_ARGS__ _IF_1_ELSE #define _IF_0(...) _IF_0_ELSE #define _IF_1_ELSE(...) #define _IF_0_ELSE(...) __VA_ARGS__ #define HAS_ARGS(...) BOOL(FIRST(_END_OF_ARGUMENTS_ __VA_ARGS__)()) #define _END_OF_ARGUMENTS_() 0 #define MAP(m, first, ...) m(first) IF_ELSE(HAS_ARGS(__VA_ARGS__))( DEFER2(_MAP)()(m, __VA_ARGS__) )( /* Do nothing, just terminate */ ) #define _MAP() MAP #define apply_(x) f(x); #define apply(...) EVAL(MAP(apply_, __VA_ARGS__))

要测试宏扩展,可以使用带有命令行参数-E的gcc:

$ gcc -E srcFile.c

因为您会收到具体的错误消息并了解发生了什么.

because your're getting concrete error messages and understand what's going on.

更多推荐

C 宏:如何将另一个宏映射到可变参数?

本文发布于:2023-11-25 21:08:19,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1631352.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:如何将   参数

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!