在C中仅在变量参数函数中打印整数参数

时间:2013-10-16 08:37:37

标签: c

我想编写一个C函数,它可以接受任意数量的参数并仅打印int个参数的值。我在va_list中看到va_argstdarg.h,但我找不到任何获取参数数量的机制。我不能把第一个参数作为参数的数量。

3 个答案:

答案 0 :(得分:2)

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

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

int foo(int number, ...);

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

参考:C FAQ: How can I discover how many arguments a function was actually called with?

答案 1 :(得分:1)

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

请注意,在常见处理器和application binary interfaces(ABI)约定(例如Linux上的x86-64 ABI)上,机器本身在运行时不知道C中当前调用的arity;其他人x86 calling conventions也是如此。但是,当编译器正在编译一个可变参数调用时,它确实在编译时知道arity(但不会在目标文件中发出它)。

您可以定义变量函数作为第一个参数作为剩余(可变参数)参数的数量的约定:

  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)你可能会遇到噩梦。

要简短:我建议放弃这个目标并做其他事情。

答案 2 :(得分:0)

使用NARGS宏(在这种情况下限制为8个args):

#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;
}