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
无关

这意味着code
val=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
的实现中,没有对type
float
调用
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)