具有最小参数的可变参数函数

时间:2013-01-04 15:08:22

标签: c parameters

  

可能重复:
  C++ preprocessor __VA_ARGS__ number of arguments
  How to count the number of arguments passed to a function that accepts a variable number of arguments?

为了学习变量参数功能,我写了一个演示:

#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>

int foo(int n, int m, ...);

int
main ( int argc, char *argv[] )
{
    int n = 10;
    int m = 15;
    int p = 20;
    //   foo (n, m);
    foo (n, m, 20);

    return EXIT_SUCCESS;
}

int foo (int n, int m, ...)
{
    va_list ap;
    int p;
    char *str;

    va_start (ap, m);
    p = va_arg (ap, int);
    n = m + p;
    printf ("%d.\n", n);
    va_end (ap);
    return 0;
}

如果只有2个参数,我想知道如何处理该函数。 (对于此演示,如果只有nm,则在运行foo后,我想获得结果:n = n+m

4 个答案:

答案 0 :(得分:1)

对于每个变量参数('variadic')函数,必须有一种方法让函数知道它必须处理多少个参数。有各种方法可以处理。

  • printf()scanf()系列函数使用格式字符串来确定传递给函数的参数数量。
  • POSIX open()函数查看第二个参数中的选项,以了解是否存在第三个参数。
  • POSIX execl()函数会一直扫描,直到遇到空指针参数。
  • 您可以传递要处理的参数数量的明确计数(请example参见Fei Jiang)。

所有这些方法都有效。 open()机制是最不通用和最特殊的(主要来自历史怪癖)。

但必须使用一种这样的机制。被调用的函数必须能够(以某种方式)告诉它何时完成了对其参数列表的变量部分的处理。

除非您将可变长度参数列表转发给其他函数(例如,使用vsnprintf()格式化传递给函数的变量参数的字符串),您的可变参数函数体将需要一个循环来处理可变数量的参数。你的功能缺少那个循环。

答案 1 :(得分:1)

在运行时,无法从va_list中了解其他参数的实际数量。因此,应该有另一种方法来推断这个数字,例如来自先前的参数或来自某些列表末尾的约定(如同,给出任意数量的指针后跟NULL)。考虑printf,其中格式字符串确定va_list部分中预期的参数(具体类型)。

只要考虑到这一点,最小参数数量就没有什么特别之处(即空的va_list)。当你知道没有什么可以期待的时候,不要从va_list弹出任何东西。

答案 2 :(得分:1)

我不明白你想要'foo'做什么,但通常foo应该有一个循环,而foo应该被告知多少参数它在调用时给出,或者更确切地说,当循环结束时给出。 printf在第一个char * pattern参数

中通过%d%s%f ...知道这一点

例如,如果我们想编写一个返回几个整数之和的函数,我们可以像这样实现

#include <stdio.h>
#include <stdarg.h>
int int_sum(int count, ...) {
    int sum = 0, i;
    va_list ap;
    va_start(ap, count);
    for (i = 0; i < count; ++i) {
        sum += va_arg(ap, int);
    }
    va_end(ap);
    return sum;
}

int main() {
    printf("%d\n", int_sum(5, 1, 2, 3, 4, 5));
    return 0;
}

答案 3 :(得分:0)

不确定我是否理解了这个问题,但是如果你在varlist函数中只有一个参数,例如foo(int n,...),然后是...,然后你可以在va_start()中传递foo的第一个参数(在我们的例子中为n),它将始终有效。

int foo (int n,  ...);
int
main ( int argc, char *argv[])
{
    int n = 10;
    int m = 15;
    int p = 20; 

    foo (n, m);
    //  foo (n, m, 20);

    return EXIT_SUCCESS;
}

int foo (int n,  ...)
{
    va_list ap;
    int p;
    char *str;

    va_start (ap, n);
    p = va_arg (ap, int);
    n = n + p;
    printf ("%d.\n", n);
    va_end (ap);
    return 0;
}