我已经知道C Preprocessor, Macro "Overloading"VA_NARGS
中描述的宏
有一段时间了,但我总是被让它工作所需的大量样板文件所推迟。
我最近需要这个功能,所以我咬紧牙关,写了所有必要的宏代码,尽其“荣耀”。
在我的特殊情况下,我可以始终依赖所有 varargs 参数为特定类型。这让我想到也许有更好的方法,使用sizeof
数组类型。我在我的本地系统上试过这个,它似乎工作。但是,我担心这个解决方案可能很脆弱(超出类型限制)。
我的问题是:这实际上是解决问题的安全且合理的解决方案吗?或者也许:如果我使用这个,我会问什么麻烦?最后:如果尝试存在问题(如下),是否可以应用调整以挽救一般方法?
这是代码以及演示main()
功能。在这种情况下,可变参数参数都必须是整数:
#include <stdio.h>
#define ARG_ARRAY(...) ((int[]) { __VA_ARGS__ })
#define ARG_COUNT(...) (sizeof (ARG_ARRAY(__VA_ARGS__)) / sizeof (int))
#define STUFF(label, ...) \
stuff(label, ARG_COUNT(__VA_ARGS__), ARG_ARRAY(__VA_ARGS__))
void stuff(char *label, int count, int *values) {
printf("[%s] count %d", label, count);
for (int i = 0; i < count; i++) {
printf("%s %d", (i == 0) ? ":" : ",", values[i]);
}
printf("\n");
}
int return1(void) {
printf("Called `return1()`.\n");
return 1;
}
int main(int argc, char **argv) {
STUFF("blort");
STUFF("frotz", return1());
STUFF("fizmo", 2 + 3, 6 + 1);
STUFF("glorf", 99, 999, 999);
STUFF("igram", 9, 8, 7, 6, 5, 4, 3, 2, 1);
}
这是一个成绩单:
[blort] count 0
Called `return1()`.
[frotz] count 1: 1
[fizmo] count 2: 5, 7
[glorf] count 3: 99, 999, 999
[igram] count 9: 9, 8, 7, 6, 5, 4, 3, 2, 1
return1()
打印输出是为了验证该函数没有被调用两次。
更新:
评论中指出的(int[]) { args }
是 C99 但不是 C++。在我的情况下,我可以指望对有问题的代码使用 C 编译器,但了解这个特殊限制仍然很好。
在一个现已删除的答案中指出,C99 要求一个可变参数宏参数至少由一个实际参数填充(尽管我认为规范在这方面充其量是模棱两可的)。我手头的编译器(OS X 上的 Clang)接受代码,-Wall
但实际上抱怨-pedantic
,正如@2501 在他们的评论中恰当地展示的那样。
-pedantic
还抱怨一个零大小的数组(无参数扩展(int[]) { }
),尽管这可以通过始终包含一个虚拟元素来解决。