宏内的变量参数

我有两个函数foo1(a,b)&foo2(a,b,c)和一个宏

#define add(a,b) foo(a,b) 

我需要重新定义宏来完成,

1.如果使用2个参数调用add(),则调用foo1

  1. 如果使用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.