我编写了一个包含可变参数的小型 C 程序。见下文:-
#include <stdio.h>
#include <stdarg.h>
double calculateAverage(int num,...)
{
va_list argumentList;
double sum=0;
int i;
va_start(argumentList,num);
for(i = 0; i < num; i++)
{
sum += va_arg(argumentList,double);
}
va_end(argumentList);
return(sum/num);
}
int main()
{
printf("%f\n",calculateAverage(3,1,2,3));
printf("%f\n",calculateAverage(4,2,4,6,8));
printf("%f\n",calculateAverage(4,2.0,4.0,6.0,8.0));
printf("%f\n",calculateAverage(3,1,2,3));
}
输出是:
0.000000
0.000000
5.000000
5.333333
只有 calculateAverage(4,2.0,4.0,6.0,8.0)
给出了预期的输出,即当我特别用小数点表示它们时。
不应该
va_arg(argumentList,double)
安全地将数字提升为两倍吗?calculateAverage(3,1,2,3)
如何在 2 个不同的地方给出 2 个结果?我是否在某些“未定义行为”领域内?如果是,怎么办?
我使用的是 gcc 4.8.1 版。
最佳答案
不,不应该。使用 va_arg()
,您可以指定假定数据的格式。关于内部表示,1.0
看起来与 1
完全不同。如果您将 1
当作 double
,就会出现完全错误的情况。
以下是运行函数调用时堆栈上发生的情况:
double calculateAverage(int num,...)
{
va_list argumentList;
double sum=0;
int i;
va_start(argumentList,num);
printf("%p", &num);
unsigned char * c = #
for(i = 0; i < num * sizeof(double) + 4; i++, c++)
{
printf(" %02x", *c);
}
printf("\n");
for(i = 0; i < num; i++)
{
sum += va_arg(argumentList,double);
}
va_end(argumentList);
return(sum/num);
}
然后,
printf("%f\n",calculateAverage(3,1,2,3));
给予
0xbfc507d0 03 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 ...
-0.054776
鉴于
printf("%f\n",calculateAverage(3,1.0,2.0,3.0));
给予
0xbfd15290 03 00 00 00 00 00 00 00 00 00 f0 3f 00 00 00 00 00 00 00 40 00 00 00 00 00 00 08 40
2.000000
因为整数 1
在内部看起来像 00 00 00 01
而 1.0
在内部看起来像 00 00 00 00 00 00 f0 3f
(都在小端机器上)。
将诸如 00 00 00 01 00 00 00 02
之类的堆栈内容解释为 double 会导致奇怪的结果。
关于c - 具有可变参数的函数 - 奇怪的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19605284/