2

可能的重复:
C++ 预处理器 __VA_ARGS__ 参数数量
如何计算传递给接受可变数量参数的函数的参数数量?

为了学习变参函数,我写了一个demo:

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

如果它只有两个参数,我想知道如何处理该函数。(对于这个演示,如果只有nand m,运行后foo,我想得到结果:n = n+m。)

4

4 回答 4

1

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

  • 和系列函数使用格式字符串printf()scanf()确定传递给函数的参数数量。
  • POSIXopen()函数查看第二个参数中的选项以了解是否有第三个参数。
  • POSIXexecl()函数扫描直到遇到空指针参数。
  • 您可以将参数数量的显式计数传递给处理(参见Fei Jiang示例)。

所有这些方法都有效。该open()机制是最不普遍和最奇特的(主要源于历史怪癖)。

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

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

于 2013-01-04T15:55:10.350 回答
1

在运行时,无法从 va_list 中知道附加参数的实际数量。因此应该有另一种方法来推断这个数字,例如从以前的参数或从一些列表末尾约定(如,给出任意数量的指针,后跟 NULL)。考虑printf,其中格式字符串确定 va_list 部分中期望的参数数量(什么类型)。

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

于 2013-01-04T15:58:04.187 回答
1

我不明白你想让 'foo' 做什么,但通常 foo 应该有一个循环,并且应该告诉 foo在调用时给出了多少参数,或者更确切地说,当循环结束时。printf 在第一个 char* 模式参数中通过 %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;
}
于 2013-01-04T16:00:27.323 回答
0

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

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;
}
于 2013-01-04T15:32:28.307 回答