1

In Visual Studio 2012, when I run the following code, which just calculates the average of numbers, gives an erroneous answer. The for loop - for some reason - starts on Number = 1 and goes one entry beyond Number = 9.

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

float avg(int Count, ...)
{
    va_list Numbers;
    va_start(Numbers, Count);
    int Sum = 0;
    for(int i = 0; i < Count;  ++i)
    {
        int entry = va_arg(Numbers, int);
        printf("%d   %d\n", i, entry);
        Sum += entry;   
    }
    va_end(Numbers);

    float av = Sum/Count;
    return(av);
}

int main()
{
    float Average = avg(10, 1, 2, 3, 4, 5, 6, 7, 8, 9);
    printf("The average of the first 10 whole numbers: %f\n", Average);
}

I checked e.g. Passing variable number of arguments around but I can't figure out why va_arg pulls the second entry from Numbers first. The result of this code on my machine is:

0   1
1   2
2   3
3   4
4   5
5   6
6   7
7   8
8   9
9   790803
The average of the first 10 whole numbers: 79084.000000
Community
  • 1
  • 1
Ferenc
  • 884
  • 9
  • 19

2 Answers2

3

When you use va_arg(), it only processes the variable parts of the argument list, not the initial part with named parameters. So the first call to va_arg gets entry = 1 because that's the first argument in the variable part.

The Number argument should be the count of additional arguments, it shouldn't count itself. Since you're only passing 9 variable arguments, you should call it as

float Average = avg(9, 1, 2, 3, 4, 5, 6, 7, 8, 9);

Also, when you calculate the average, one of the division operands needs to be float. Otherwise, it will calculate an integer quotient, which rounds the result, and then assign that rounded result to the av variable. A simple solution is to declare Sum to be float instead of int.

Barmar
  • 741,623
  • 53
  • 500
  • 612
2

Because you have set Count to 10. If you tell avg that there are 10 numbers, but you only supply 9, you are invoking undefined behavior.

Jim Buck
  • 20,482
  • 11
  • 57
  • 74