繁体   English   中英

变量函数(va_arg)不适用于float,而printf有效吗? 有什么区别?

[英]Variadic function (va_arg) doesn't work with float, while printf does? What the difference is?

我碰巧在两年的这个问题中遇到了类似的情况:

变量函数(va_arg)不适用于float?

有人说,当我们称之为的时候,问题是促使浮动加倍

    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_argprintf或任何其他具有可变参数数量的函数获得控件时,所有的float都已被提升为double s; 原始float不可用于检索。

之间的差printfva_argprintf遵循由标准设立的规则,并请求一个提升的类型(即,参数double )时,看到在格式字符串对应的格式说明。 因此,它成功地获得了一个doublefloat值,并产生了所需的输出。

另一方面,当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.

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