来自之前的question:
如果您尝试将
float
传递给printf
,则会将其提升为double
在printf
收到它之前
printf()
是一个可变函数对吗?因此,变量函数在传递float
之前会向double
提升{{1}}参数吗?
答案 0 :(得分:23)
是的,variadic函数的float参数被提升为double。
draft C99 standard部分6.5.2.2
函数调用说:
来自draft C++ standard部分[...]和论点 将float类型提升为double。这些被称为默认参数 促销。[...]
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
(这是我们许多程序员在使用浮点数时默认的)。
通过观察可以看出:
3.14
是double
(如果您想要float
,则必须采取额外步骤并追加f
)double
(例如,sin()
需要double
;如果您需要float
,则必须使用sinf()
float
1}})有了这个,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 conventions和ABI更简单。
将float
视为一种short double
(当然,C中的非法)。 float
主要用于压缩内存(并且可以承受精度损失)时非常有用。另请参阅http://floating-point-gui.de/了解更多信息。