宏内的变量参数
我有两个函数foo1(a,b)&foo2(a,b,c)和一个宏
#define add(a,b) foo(a,b)
我需要重新定义宏来完成,
1.如果使用2个参数调用add(),则调用foo1
- 如果使用3个参数调用add(),则调用foo2
我是选项VA_ARGS的新手。 我怎样才能做到这一点
如果你必须使用可变参数宏,那么这是一个技巧。
#define add(...) _Generic ( &(int[]){__VA_ARGS__}, \ int(*)[2]: add2, \ int(*)[3]: add3) (__VA_ARGS__)
- 让宏创建一个复合文字数组。 此数组的大小取决于参数的数量。
- 获取复合文字的地址,以获取数组指针类型。
- 让
_Generic
检查你得到的类型,然后根据它调用适当的函数。
这是100%标准C,也是类型安全的。
演示:
#include #define add(...) _Generic ( &(int[]){__VA_ARGS__}, \ int(*)[2]: add2, \ int(*)[3]: add3) (__VA_ARGS__) int add2 (int a, int b); int add3 (int a, int b, int c); int main (void) { printf("%d\n", add(1, 2)); printf("%d\n", add(1, 2, 3)); //printf("%d\n", add(1, 2, 3, 4)); Compiler error for this. } int add2 (int a, int b) { return a + b; } int add3 (int a, int b, int c) { return a + b + c; }
计算参数的常用技巧可能会适用于此:
#define ADD_EXPAND(...) \ ADD_EXPAND_(__VA_ARGS__, EXPAND_ADD_FUNCS()) #define ADD_EXPAND_(...) \ EXPAND_ADD_SEL_FUNC(__VA_ARGS__) #define EXPAND_ADD_SEL_FUNC(first_, second_, third_, func, ...) func #define EXPAND_ADD_FUNCS() foo2, foo, dummy #define add(...) ADD_EXPAND(__VA_ARGS__)(__VA_ARGS__)
一旦你翻过锅炉板,它基本上只需要将所有参数放在一行中,然后将函数标记放在它们之后,并查看哪个函数突出。 这就是EXPAND_ADD_SEL_FUNC
作用。
你可以在coliru上看到它。
但我会重申我们在评论中告诉你的内容。 这可能是适当function的低于标准的解决方案。 我没有彻底测试过,所以很容易破损。 使用风险由您自己承担。
如果您只想区分两个函数,则以下工作:
#define ADD(_1, _2, _3, X, ...) X #define add(...) ADD(__VA_ARGS__, add3, add2, 0)(__VA_ARGS__)
辅助宏ADD
总是选择第四个参数:
add(a, b) --> ADD(a, b, add3, add2, 0) --> add2 add(a, b, c) --> ADD(a, b, c, add3, add2, 0) --> add3
缺点是当您不向函数提供两个或三个参数时,会收到相当神秘的错误消息。
可变function的优势在于您可以获得类型安全性。 例如,如果你的函数在double
s上运行,你仍然可以说add(1, 2)
,整数参数将转换为double
s。 并且可变参数函数需要关于实际参数数量的一些额外信息,因此这不是一个可行的解决方案,除非您在函数中指定了加数的数量。
附录 :我已经更改了add
宏,因此它不会将空的可变参数列表传递给ADD
。 有些编译器允许空列表,但它不是标准C.