为什么printf()将float提升为double?

时间:2015-01-22 19:57:48

标签: c++ c floating-point printf variadic-functions

来自之前的question

  

如果您尝试将float传递给printf,则会将其提升为double   在printf收到它之前

printf()是一个可变函数对吗?因此,变量函数在传递float之前会向double提升{{1}}参数吗?

4 个答案:

答案 0 :(得分:23)

是的,variadic函数的float参数被提升为double。

draft C99 standard部分6.5.2.2函数调用说:

  

[...]和论点   将float类型提升为double。这些被称为默认参数   促销。[...]

来自draft C++ standard部分5.2.2函数调用的

  

[...]浮点类型,受浮点影响   升级(4.6),将参数的值转换为   在通话前提升类型。 [...]

和第4.6部分:

  

float类型的prvalue可以转换为double类型的prvalue。值未改变

cppreference涵盖了C ++中可变参数函数的default conversions

  
      
  • std :: nullptr_t转换为void *
  •   
  • 浮点参数在浮点提升中转换为double
  •   
  • bool,char,short和unscoped枚举转换为int或更宽整数类型,如整数提升
  •   

我们可以在C中看到,并且可能在C ++中看到这种转换是为了与 K&amp; RC 的兼容,来自Rationale for International Standard—Programming Languages—C强调我的):< / p>

  

为了与过去的做法兼容,所有参数促销都以   在没有原型声明的情况下在K&amp; R中描述,包括   并不总是希望推广浮动加倍

答案 1 :(得分:15)

至于为什么部分问题,很简单:C(和C ++)标准认为double是“默认”浮点类型。不是float(这是我们许多程序员在使用浮点数时默认的)。

通过观察可以看出:

  1. 3.14double(如果您想要float,则必须采取额外步骤并追加f
  2. 标准数学函数默认使用double(例如,sin()需要double;如果您需要float,则必须使用sinf() float 1}})
  3. 有了这个,double在可变参数函数调用中被提升为double似乎更“自然”,因为{{1}}是语言中的“自然”默认值

答案 2 :(得分:14)

给定函数原型,当在尾随参数中使用时,类型float仅自动提升 1 。功能打印使用:

int printf(const char * restrict format, ...);

1 (引自:ISO / IEC 9899:201x 6.5.2.2函数调用)
6.对每个参数执行整数提升,并对其进行参数化 将float类型提升为double。这些被称为默认参数 促销活动。
7.默认参数 促销是在尾随参数上进行的。

答案 3 :(得分:11)

因为(C99或C11)标准是这样说的。请参阅answer by 2501

有几个实用的原因:历史(C的第一个实现已用于系统编程,其中浮点运算无关紧要),以及当前(平板电脑,台式机,服务器...)的事实处理器,double上的算术运算效率与float一样高(但是一些廉价的微控制器没有任何FPU,或者只能通过硬件添加float,并且每个都需要一个库对double)的操作。最后,我猜这样的规则可以使calling conventionsABI更简单。

float视为一种short double(当然,C中的非法)。 float主要用于压缩内存(并且可以承受精度损失)时非常有用。另请参阅http://floating-point-gui.de/了解更多信息。