使用变量参数使用va_arg进行类型转换错误

时间:2014-05-27 12:50:32

标签: c variadic-functions

我写了这个简单的代码,用变量参数找到数字的平均值 -

#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;
}

每个输入的数字都会转换为double。但是如果我在avg()中传递给main()的参数中输入4而不是4.0,编译器似乎无法正确输入它。有人能指出这背后的机制吗?

2 个答案:

答案 0 :(得分:3)

当然,编译器在编译va_arg()电话时,不知道您在avg()的电话中如何挑选参数。

类型必须匹配,因为例如intdouble通常具有不同的大小。根据编译器用于传递参数的确切机制,如果您输入一个大小的值,并且取出另一个大小,则可能导致错误匹配。不好,不要这样做。

获得这种安全性的一种方法是使用printf() - 样式规范字符串,因为许多编译器会检查这些字符串以使参数匹配。

答案 1 :(得分:2)

当你传递4时,它不会被提升,因为参数不在参数列表中。 4作为int传递。

你的va_arg宏会将堆栈变量的地址转换为double的指针并取消引用它,但那里的内存代表一个int。

它基本上是这样做的:

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

不是这个:

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