【问题标题】:Variable argument list: use va_list or address of formal parameter?变量参数列表:使用 va_list 还是形式参数的地址?
【发布时间】:2013-08-22 14:17:58
【问题描述】:

下面的代码包含 2 个函数,这两个函数都计算提供的整数值列表的总和:

#include <iostream>
#include <stdarg.h>

using namespace std;

int sum_1 ( int number_of_values, ... )
{
    va_list arguments;
    va_start ( arguments, number_of_values );
    int sum = 0;
    for ( int i = 0; i < number_of_values; i++ )
    {
        sum += va_arg ( arguments, int );
    }
    va_end ( arguments );

    return sum;
}

int sum_2 ( int number_of_values ...)
{
    int sum = 0;
    for ( int i = 0; i < number_of_values; i++ )
        sum += *( &number_of_values + i + 1 );
    return sum;
}


int main()
{
    cout << sum_1(3, 1, 2, 3) << endl; //prints 6
    cout << sum_2(3, 1, 2, 3) << endl; //prints 6
}

sum_1 使用va_list 方法,sum_2 使用提供的number_of_values 变量的地址,相对于它找到其他值并将它们相加。

那么这两种方法有什么区别呢?使用哪一个?第二个看起来更短,那么定义va_listva_startva_artva_end 时需要注意什么?

【问题讨论】:

    标签: c++ list sum variadic-functions addressof


    【解决方案1】:

    第二个版本是不可移植的,这是使用第一个版本的有力论据。

    只有在您的平台上,函数的参数以特定方式在堆栈上布局时,第二个版本才有效。可变参数的使用将其抽象化,这就是使第一个版本具有可移植性的原因。

    【讨论】:

    • 您能否描述一下第二个版本中断的环境以及以何种方式中断?
    • @Vadim:例如,您的第二个版本不适用于我使用 g++ 4.6 的 x86_64 Linux 机器
    • 并且... 版本应该是va_list 版本的包装器,以允许转发调用(例如有多少自定义日志函数将调用转发到v*printf()
    • @Vadim:第二个版本不起作用here at ideone,它使用C++ 4.8.1 (gcc-4.8.1),不过我不知道ideone的机器架构。
    【解决方案2】:

    第二种方法假设参数如何传递给函数。不要求满足这些假设。这就是va_list 及其伙伴存在的原因:库供应商知道如何传递参数,并且可以正确实现代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-15
      • 2017-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-22
      相关资源
      最近更新 更多