2

The code below contains 2 functions both of which calculate a sum of supplied list of integer values:

#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 uses va_list approach, sum_2 uses address of supplied number_of_values variable relatively to which it finds other values and adds them up.

So what's the difference between these 2 approaches? Which one to use? Second one looks shorter, so what was care to define va_list, va_start, va_art and va_end?

Vadim Drokov
  • 109
  • 6

2 Answers2

3

The second version is non-portable, which is a strong argument for using the first version.

The second version would only work if on your platform the function's arguments are laid out on the stack in a particular fashion. The use of varargs abstracts that away, which is what makes the first version portable.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • Could you please describe an environment in which the second version breaks and in which way? – Vadim Drokov Aug 20 '13 at 13:48
  • 1
    @Vadim: As an example, your second version does not work on my x86_64 Linux box using g++ 4.6 – NPE Aug 20 '13 at 13:49
  • 1
    And the `...` version should be a wrapper to a `va_list` version, to allow forwarding calls (like how many custom log functions forward calls to `v*printf()`) – Medinoc Aug 20 '13 at 13:49
  • 1
    @Vadim: The second version doesn't work [here at ideone](http://ideone.com/gNZkjR) which uses `C++ 4.8.1 (gcc-4.8.1)` and I don't know the machine architecture at ideone, though. – Nawaz Aug 20 '13 at 13:52
2

The second approach makes assumptions about how arguments are passed to the function. There is no requirement that those assumptions be met. That's why va_list and its buddies exist: the library vendor knows how arguments are passed, and can implement the code correctly.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165