[英]Variadic function (va_arg) doesn't work with float, while printf does? What the difference is?
我碰巧在两年的这个问题中遇到了类似的情况:
有人说,当我们称之为的时候,问题是促使浮动加倍
va_arg(arg, float)
我的问题是在这篇文章的最后,但首先让我们来看看@ Jack在上面链接的问题下面的答案:
#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;
}
输出:
3.300000
4.400000
现在,如果我们将val = va_arg(vl, double)
更改为val = va_arg(vl, float)
,我们将得到(至少我进入MSVS 2012):
36893488147419103000.000000
2.162500
我们现在回答我的问题。
在这个主题中: C / C ++ va_list没有正确地返回参数最多的投票答案,并且它的评论说printf
也将 float
的提升为double
。
但有什么区别? 如果它们都将float
提升为double
,为什么printf
正确地写入值,而va_arg
会给我们这样一个鼻子恶魔?
它不是printf
,它将float参数提升为double
,它是编译器 。 换句话说,当你的va_arg
或printf
或任何其他具有可变参数数量的函数获得控件时,所有的float
都已被提升为double
s; 原始float
不可用于检索。
之间的差printf
和va_arg
是printf
遵循由标准设立的规则,并请求一个提升的类型(即,参数double
)时,看到在格式字符串对应的格式说明。 因此,它成功地获得了一个double
的float
值,并产生了所需的输出。
另一方面,当va_arg
调用val = va_arg(vl, float)
它会忽略促销规则,并获得无效的表示形式。
变量参数函数的参数获得特殊的促销规则。
这里相关的一个是将float作为变量参数传递给double。 这意味着您不能将参数作为float提取,因为它已作为double传递。 这是由编译器完成的,它与printf
无关。
这意味着代码val = va_arg(vl, float)
无效,因为参数不是float,它是double。 如果你真的需要将传入的值作为浮点数来处理,那么你最多可以做到
float val = (float) va_arg(vl, double)
请注意,printf的%f
说明符期望参数类型为double
,而不是float
printf
不接受float
类型的参数。
例如, "%f"
格式说明符需要double
类型的参数。 "%Lf"
需要long double
类型的参数。 没有格式需要一个float
类型的参数(无论如何都会提升为double
,而不是printf
本身,而只是因为调用variadic函数的语义)。
因此假设printf
是用C实现的,并且它使用<stdarg.h>
机制来读取它的参数,在printf
的实现中没有为float
类型调用va_arg()
。
任何尝试为类型float
调用va_arg()
可变函数都将具有未定义的行为,因为这样的函数不能有float
参数。 printf
有效,因为它没有这样做。
但有什么区别? 如果它们都将
float
提升为double
,为什么printf
正确地写入值,而va_arg
会给我们这样一个鼻子恶魔?
除了事实(在问题本身中说明)之外,没有区别, printf
的编码方式是将float
视为double
。 换句话说,在printf
内部的某个地方,当格式字符串包含应该有浮点数的信息时,该函数会执行va_arg(vl, double)
,就像你一样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.