浮点提升:stroustrup vs编译器——谁是对的

floating-point promotion : stroustrup vs compiler - who is right?

本文关键字:编译器 vs stroustrup      更新时间:2023-10-16

在Stroustrup的新书《c++编程语言-第四版》的10.5.1节中,他说,在执行算术运算之前,使用整型提升从较短的整数类型中创建整型,类似地,使用浮点提升从浮点数中创建双精度。

我用以下代码确认了第一个索赔:

#include <iostream>
#include <typeinfo>
int main()
{
    short a;
    short b;
    std::cout << typeid(a + b).name() << std::endl;
}

用vc++输出"int",用gcc输出"i"。

但是用float而不是short来测试它,输出仍然是"float"或"f":

#include <iostream>
#include <typeinfo>
int main()
{
    float a;
    float b;
    std::cout << typeid(a + b).name() << std::endl;
}

根据Stroustrup,浮点提升规则没有例外,所以我希望输出"double"或"d"。

提到的关于促销的部分是错误的还是不清楚的?c++ 98和c++ 11在类型提升方面有什么不同吗?

我不知道Stroustrup的书到底说了什么,但是根据标准,在这种情况下,float s不会转换为double s。在应用大多数算术二进制运算符之前,先应用5p9中描述的常用算术转换:

  • 如果其中一个操作数是范围枚举类型(7.2),则不执行转换;如果另一个操作数不具有相同的类型,则表达式是病态的。
  • 如果其中一个操作数为长双精度类型,另一个操作数应转换为长双精度类型。
  • 如果其中一个操作数为双精度,则另一个操作数转换为双精度。
  • 如果其中一个操作数为浮点数,则另一个操作数转换为浮点数。
  • 否则,两个操作数都要进行积分提升(4.5)。[…]

积分升序是导致两个short s转化为int s的原因。但是根据这些规则,两个float不会转换为double。如果将float添加到double,则float将转换为double

以上代码来自c++ 11。c++ 03包含相同的规则,除了引用作用域枚举的规则。

与此同时,Stroustrup似乎认识到引用句是不正确的,或者至少是误导性的。他从10.5.1节中删除了关于浮点提升的句子。

请参阅Stroustrup网页上的第4版第3版勘误表:

pg 267: s/类似地,浮点提升用于从浮点数中创建双精度对象//

(注:表达式s/regexp/replacement/类似于sed unix工具语义。它搜索模式regexp并用replacement替换它。)