简体   繁体   English

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

[英]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. 每个输入的数字都将转换为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. 但是如果我在main()传递给avg()的参数中输入4而不是4.0,则编译器似乎无法正确输入它。 Can anyone point out the mechanism behind this? 有人能指出这背后的机制吗?

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. 当然,编译器在编译avg()调用时不知道如何在调用va_arg()时调用参数。

The types have to match, since for instance int and double often have different sizes. 类型必须匹配,因为例如intdouble通常具有不同的大小。 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. 获得这种安全性的一种方法是使用printf()样式的规范字符串,因为许多编译器会检查这些字符串以使参数匹配。

When you pass a 4 it is not promoted because the argument is not on the parameter list. 当您传递4时,它不会被提升,因为参数不在参数列表中。 The 4 is passed as an int. 4作为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. 你的va_arg宏会将堆栈上变量的地址转换为double的指针并取消引用它,但那里的内存代表一个int。

It is basically doing this: 它基本上是这样做的:

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

Not this: 不是这个:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM