C函数中的变量参数列表 - 如何正确遍历arg列表?

时间:2010-01-02 14:29:41

标签: c function variables arguments

在以下C程序中,我收到警告:

warning #2030: '=' used in a conditional expression.

究竟是什么问题,我该如何避免这种情况?迭代变量参数的正确方法是什么?

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

int Sum(int a, int b, ...)
{
    int arg;
    int Sum = a + b;

    va_list ap;
    va_start(ap, b);

    while(arg = va_arg(ap, int))
    {
        Sum += arg;
    }
    va_end(ap);

    return Sum;
}

int main(int argc, char *argv[])
{
    printf("%d\n", Sum(1, 2, 4, 8));

    return 0;
}

5 个答案:

答案 0 :(得分:5)

你正在做的事情是惯用的,如果有点丑陋C.

为了说服编译器你知道你在做什么,你可以把这个分配包装成一组额外的括号:

while((arg = va_arg(ap, int)))

应该注意警告。

更新:

  

在赋值周围添加括号似乎并没有在使用(PellesC)的C99编译器中抑制警告。 - Gary Willoughby

什么,它没有?然后你需要让测试更加明确:

while((arg = va_arg(ap, int)) != 0)

应该做的伎俩。它也可以被认为更具可读性。


你会问我“有点丑陋”是什么意思。

从使用其他语言开始,我习惯于在测试和修改之间进行明确的分离。你正在用while的值进行测试,但同时产生副作用(即在下一个参数中读取)。正如我所说,这被认为是很正常的,因为很多C程序员都这样做,所以在C语言中是“惯用的”;我认为在K&amp; R中甚至有类似代码的例子。

根据个人喜好,我可能会将其重写为:

while (1) {
  arg = va_arg(ap, int);
  if (!arg) break;
  ...
}

这明确地将赋值与测试分开,并使循环独立于(可能)无限循环。很多人会认为我的代码更难看;正如我所说,这是个人偏好的问题。

答案 1 :(得分:1)

警告是关于:

while(arg = va_arg(ap, int))

并且说“你确定你没有意思:”

while(arg == va_arg(ap, int))

在这种情况下,你不是这样,你可以通过说:

来压制它
while( (arg = va_arg(ap, int)) )

但是,您的代码仍然无效。如果不以某种方式提供由elipsis表示的参数数量,则无法使用可变参数函数。例如,printf使用%sign:

执行此操作

printf(“%s%d%p”,x,y,z);

表示elpisis表示三个参数。

在你的情况下,你可以使用零作为整数列表中的终止值 - 这就是你的循环所暗示的。

答案 2 :(得分:0)

while(arg = va_arg(ap, int))更改为while((arg = va_arg(ap, int)))

警告是由于您在一个语句中分配和检查赋值的值而引起的。

答案 3 :(得分:0)

编写函数的另一种方法:

int Sum(int a, ...)
{
    int sum = 0;
    int current = a;

    va_list args;
    va_start(args, a);

    for(; current; current = va_arg(args, int))
        sum += current;

    va_end(args);

    return sum;
}

它摆脱了(无用的)第二个命名参数,并将参数指针的增量移出循环条件。

答案 4 :(得分:0)

示例代码

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

int add(int num, ...) {
    va_list vaList;
    int sum = 0;
    va_start(vaList, num);
    for (int i = 0; i < num; ++i) {
        sum += va_arg(vaList, int);
    }
    va_end(vaList);
    return sum;
}

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

输出: 1

3

6

10

15