我想写一个 C 函数,它可以接受任意数量的参数并且int
只打印参数的值。我看到va_list
and va_arg
in stdarg.h
,但我找不到任何机制来获取参数的数量。我不能将第一个参数作为参数的数量。
3 回答
标准 C 中没有可移植的方法来获取可变参数函数中的参数数量。
解决它的常用方法是使用最右边的参数parmN
显式地提供整数个数。例如,您的函数原型可能如下所示:
int foo(int number, ...);
但根据您的问题,这不是您的选择。
没有(便携式)方法可以在运行时获取可变参数函数中的参数数量。该数字在运行时丢失(只有编译器知道)。
请注意,在通用处理器和应用程序二进制接口(ABI) 约定(例如Linux 上的x86-64 ABI)上,机器本身在运行时不知道当前 C 调用的数量;对于其他x86 调用约定也是如此。但是,当编译器编译可变参数调用时,它确实知道编译时的元数(但不会在目标文件中发出它)。
您可以定义可变参数函数将剩余(可变参数)参数的数量作为第一个参数的约定:
void print_integers (int nbints, ...);
然后你会实现它,例如
#include <stdio.h>
#include <stdarg.h>
void print_integers (int nbints, ...)
{
va_list args;
va_start (nbints, args);
for (int ix=0; ix<nbints; ix++) {
int curarg = va_arg(args, int);
printf(" %d", curarg);
};
va_end(args);
fflush(NULL);
}
如果你不能这样做,你必须定制你的预处理器或编译器。也许你的MELT扩展的工作(MELT是一种扩展 GCC 的领域特定语言)。或者也许使用GPP作为你的预处理器。
您还可以玩一些cpp预处理器技巧,特别是stringification和concatenation以及variadic macros。例如,您可以定义
void print_integers_str(const char*, ...);
#define print_my_integers(...) \
print_integers_str(#__VA_ARGS__, ##__VA_ARGS__);
然后print_my_integers(x,y)
扩展为print_integers_str("x,y", x,y)
,您的 varadic 函数print_integer_str
可以解析"x,y"
文字字符串(至少计算逗号)。但和print_my_integers(f(x,y),g(y)+/*,,*/k)
你在一起可能会做噩梦。
简而言之:我建议放弃该目标并做其他事情。
使用 NARGS 宏(在这种情况下限制为 8 个参数):
#include <stdio.h>
#include <stdarg.h>
#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)
#define fn(...) fn(NARGS(__VA_ARGS__), __VA_ARGS__)
static void (fn)(int n, ...)
{
va_list args;
int i;
va_start(args, n);
for (i = 0; i < n; i++) {
printf("%d\n", va_arg(args, int));
}
va_end(args);
}
int main(void)
{
fn(6, 7, 8);
return 0;
}
或者您可以循环直到-1:
#include <stdio.h>
#include <stdarg.h>
#define fn(...) fn(0, __VA_ARGS__, -1)
static void (fn)(int n, ...)
{
va_list args;
int i;
va_start(args, n);
while (1) {
i = va_arg(args, int);
if (i == -1) break;
printf("%d\n", i);
}
va_end(args);
}
int main(void)
{
fn(6, 7, 8);
return 0;
}