nsane
nsane

Reputation: 1765

Error typecasting with va_arg using variable arguments

I wrote this simple code to find average of numbers using variable arguments -

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

double avg(int num, ...)
{
        va_list arg_list;
        double sum=0;
        int x;

        va_start(arg_list,num);

        for(x=0;x<num;x++)
        {
                double n=va_arg(arg_list,double);
                printf("Num = %f\n",n);
                sum+=n;
        }
        va_end(arg_list);
        return sum/num;
}

int main(int argc,char *argv[])
{
        printf("%f\n",avg(2,2.0,4.0));
        return 0;
}

Each of the entered number is converted to double. But if I enter, say, 4 instead of 4.0 in the parameters passed to avg() in main(), the compiler cannot seem to type cast it properly. Can anyone point out the mechanism behind this?

Upvotes: 3

Views: 340

Answers (2)

this
this

Reputation: 5300

When you pass a 4 it is not promoted because the argument is not on the parameter list. The 4 is passed as an int.

Your va_arg macro will cast the address of the variable on the stack as a pointer to double and dereference it, but the memory there represents an int.

It is basically doing this:

int a = 4 ;
double d = *(double*)&a ;

Not this:

int a = 4 ;
double d = (double)a ;

Upvotes: 3

unwind
unwind

Reputation: 400049

Of course, the compiler has no idea how you're going to be picking out the arguments in your call to va_arg() when it compiles the avg() call.

The types have to match, since for instance int and double often have different sizes. Depending on the exact mechanism the compiler uses to pass the arguments, this can lead to mis-matches if you put in a value of one size, and take out one of another. Not good, don't do that.

One way to get this safer is to use printf()-style specification strings, since many compilers check these so that the arguments match.

Upvotes: 4

Related Questions