C++ 变量函数(va#U arg)不';不能使用float,而printf可以?有什么区别?
两年来,我碰巧遇到了类似的情况: 有人说,问题是当我们称之为C++ 变量函数(va#U arg)不';不能使用float,而printf可以?有什么区别?,c++,c,floating-point,variadic-functions,C++,C,Floating Point,Variadic Functions,两年来,我碰巧遇到了类似的情况: 有人说,问题是当我们称之为 va_arg(arg, float) 我的问题是在这篇文章的末尾,但是首先让我们看看上面提到的问题的@杰克的答案: #include <stdio.h> #include <stdarg.h> void foo(int n, ...) { va_list vl; va_start(vl, n); int c; double val;
va_arg(arg, float)
我的问题是在这篇文章的末尾,但是首先让我们看看上面提到的问题的@杰克的答案:
#include <stdio.h>
#include <stdarg.h>
void foo(int n, ...)
{
va_list vl;
va_start(vl, n);
int c;
double val;
for(c = 0; c < n; c++) {
val = va_arg(vl, double);
printf("%f\n", val);
}
va_end(vl);
}
int main(void)
{
foo(2, 3.3f, 4.4f);
return 0;
}
现在,如果我们将val=va_arg(vl,double)
更改为val=va_arg(vl,float)
,我们将得到(至少我在MSVS 2012中得到):
现在让我们来讨论我的问题
在本主题中:
大多数人投票的答案和它的评论说,printf
也将float
提升为double
但有什么区别呢?如果两者都将
float
提升为double
,为什么printf
正确写入值,而va_arg
给我们提供了这样一个鼻魔?变量参数函数的参数得到了特殊的提升规则
与此相关的一点是,将浮点作为变量参数传递会被提升为double。这意味着您不能将参数提取为浮点,因为它已作为双精度传递。这是由编译器完成的,它与printf
无关
这意味着codeval=va_arg(vl,float)
无效,因为参数不是float,而是double。
如果您真的需要将传入的值作为浮点处理,那么您最多可以这样做
float val = (float) va_arg(vl, double)
请注意,printf的
%f
说明符需要类型为double
的参数,而不是float
将float参数提升为double
的不是printf
,而是编译器。换句话说,当您的va_arg
或printf
或任何其他具有可变参数数的函数获得控制时,所有float
s已升级为double
s;原始的float
s不可检索
printf
和va_arg
之间的区别在于printf
遵循标准设置的规则,当它在格式字符串中看到相应的格式说明符时,请求升级类型的参数(即double
)。因此,它成功地获得一个double
,其中包含提升的浮点值,并生成所需的输出
另一方面,当va_arg
调用val=va_arg(vl,float)
时,它会忽略提升规则,并得到一个无效的表示
但有什么区别呢?如果两者都将float
提升为double
,为什么printf
正确写入值,而va_arg
给我们带来了这样一个鼻魔
除了(在问题本身中说明的)事实,printf
的编码方式将float
视为double
之外,没有区别。换句话说,在printf
内部的某个地方,当格式字符串包含应该有浮点数的信息时,函数会像您一样执行va_arg(vl,double)
。printf
不接受float
类型的参数
例如,“%f”
格式说明符需要类型为double
的参数<代码>“%Lf”
需要类型为long double
的参数。没有任何格式需要类型为float
的参数(无论如何,它将被提升为double
,不是通过printf
本身,而是仅仅因为对可变函数调用的语义)
因此,假设printf
是在C中实现的,并且它使用
机制来读取其参数,那么在printf
的实现中,没有对typefloat
调用va_arg()
任何尝试为类型float
调用va_arg()
的变量函数都将具有未定义的行为,因为此类函数不能有float
参数printf
之所以有效,是因为它不这样做。是什么让你认为printf
试图解析参数,它知道会被提升为double
,如float
?printf
函数总是知道在传递float
时会出现double
。您的函数不可用。这就是不同之处。谢谢你们的回答!现在我明白了,不仅仅是它的工作原理,还有更多。注意:如果printf()
的参数是char
,short
或任何小于int
的参数,同样的问题也适用于int
:需要将int
与va_arg()
一起使用。非常感谢您的回答,现在我很清楚是什么引起了这里的骚动。
36893488147419103000.000000
2.162500
float val = (float) va_arg(vl, double)