0

我想写一个 C 函数,它可以接受任意数量的参数并且int只打印参数的值。我看到va_listand va_argin stdarg.h,但我找不到任何机制来获取参数的数量。我不能将第一个参数作为参数的数量。

4

3 回答 3

2

标准 C 中没有可移植的方法来获取可变参数函数中的参数数量。

解决它的常用方法是使用最右边的参数parmN显式地提供整数个数。例如,您的函数原型可能如下所示:

int foo(int number, ...);

但根据您的问题,这不是您的选择。

参考:C 常见问题解答:我怎样才能发现一个函数实际调用了多少个参数?

于 2013-10-16T08:44:12.633 回答
1

没有(便携式)方法可以在运行时获取可变参数函数中的参数数量。该数字在运行时丢失(只有编译器知道)。

请注意,在通用处理器和应用程序二进制接口(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预处理器技巧,特别是stringificationconcatenation以及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)你在一起可能会做噩梦。

简而言之:我建议放弃该目标并做其他事情。

于 2013-10-16T08:40:38.460 回答
0

使用 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;
}
于 2013-10-16T08:43:12.480 回答