C++ 为什么printf()将浮点提升为双精度?

C++ 为什么printf()将浮点提升为双精度?,c++,c,floating-point,printf,variadic-functions,C++,C,Floating Point,Printf,Variadic Functions,从以前的: 如果您试图将一个float传递给printf,它将被提升为double 在printf收到它之前 printf()可变函数对吗?那么,在传递变量函数之前,变量函数是否将浮点参数提升为双精度?是的,变量函数的浮点参数提升为双精度 6.5.2.2函数调用部分说明: […]以及 have类型float被提升为double。这些被称为默认参数 促销活动。[…] 从5.2.2函数调用部分: […]受浮点值约束的浮点类型 升级(4.6),参数的值转换为 在调用之前升级类型。[……] 以及第4.6

从以前的:

如果您试图将一个
float
传递给
printf
,它将被提升为
double
printf
收到它之前


printf()
可变函数对吗?那么,在传递变量函数之前,变量函数是否将
浮点
参数提升为
双精度

是的,变量函数的浮点参数提升为双精度

6.5.2.2
函数调用部分说明:

[…]以及 have类型float被提升为double。这些被称为默认参数 促销活动。[…]

5.2.2
函数调用部分:

[…]受浮点值约束的浮点类型 升级(4.6),参数的值转换为 在调用之前升级类型。[……]

以及第4.6节:

float类型的prvalue可以转换为double类型的prvalue。该值保持不变

在C++中覆盖变量函数:

  • std::nullptr_t被转换为void*
  • 浮点参数转换为双精度,如同在浮点提升中一样
  • bool、char、short和unscoped枚举将转换为int或更宽的整数类型,如整数升级中所述

我们可以在C中看到,并且在C++中可以看到,这个转换是与K&R C兼容的,从(强调地雷)到:

为了与过去的实践相兼容,所有的参数升级都是按如下方式进行的 在没有原型声明的情况下在K&R中描述,包括 浮动并非总是理想的双倍提升


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

这可以通过观察来看出:

  • 3.14
    是一个
    double
    (如果您想要一个
    float
    ,您必须采取额外的步骤并附加一个
    f
  • 默认情况下,标准数学函数采用
    double
    (例如,
    sin()
    采用
    double
    ;如果需要
    float
    ,则必须使用
    sinf()
  • 这样,在变量函数调用中将
    float
    提升为
    double
    似乎更“自然”,因为
    double
    是语言中的“自然”默认值。

    因为(C99或)标准这么说。看

    这有几个实际原因:历史(最早的C实现用于系统编程,浮点运算无关紧要),以及在当前(平板电脑、台式机、服务器等)处理器上,
    double
    上的算术运算与
    float
    上的运算效率相当(但是一些便宜的微控制器没有FPU,或者只能通过硬件添加
    浮点
    ,并且在
    双精度
    上的每个操作都需要一个库)。最后,我想这样的规则可以实现稍微简单一些的s


    float
    看作是一种
    短双精度
    (这在C中当然是非法的)。当需要压缩内存时,
    float
    最有用(并且可以承受精度损失)。有关更多信息,请参见。

    给定函数原型,只有在尾部参数中使用类型float时,才会自动升级1。函数print使用这些参数:

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

    1(引用自:ISO/IEC 9899:201x 6.5.2.2函数调用)
    6.对每个参数执行整数升级,并且 have类型float被提升为double。这些被称为默认参数 促销活动。
    7.默认参数
    对尾部参数执行升级。

    是,通过“默认参数升级”。类似地,
    char
    升级为
    int
    ,因此
    char c=127;printf(“%d”,c);
    也能正常工作。您愿意将double降级为float吗?您愿意增加每种类型独立于其他密切相关类型的复杂性吗?对我来说,提升float似乎是一个常识性的解决方案。我认为这句话不完全正确(或不包括完整的上下文)当传递给函数时,
    float
    值并不总是转换为
    double
    ,但当它们作为尾部参数传递给var-args函数时,如
    printf
    。您的引用被错误引用,或者可能来自旧版本。通过谷歌搜索
    C Primer Plus
    会在实际引用的地方找到一个“这是因为C在将类型浮点值作为参数传递给任何函数(如printf())时,会自动将类型浮点值扩展为类型double,该函数没有显式地对参数类型进行原型化。”“Not
    float
    是我们许多程序员在使用浮点数时的默认设置)。“我不知道其他人是怎么做的,但我通常会加倍努力。如果是关于存储e,我只能求助于
    float
    。G大量具有相当高内在误差的测量数据需要存储在一个文件中。我对C的一大遗憾是,当添加
    long double
    时,没有包含任何机制来指定变量函数是否期望所有浮点值都转换为最长类型(
    long double
    ),特定类型
    double
    ,或者它期望以不同方式传递
    long double
    double
    。依我看,如果代码可以说“将所有整数ish转换为这种类型,将所有浮点ish转换为这种类型”,那么多年来就会节省大量的时间和可移植性问题。C99或C11标准在哪里这么说?请您提供一份来自《标准》的准确引文,好吗?“因为[…]标准是这么说的”。《C编程语言》(1978年第1版)b也是如此