使用双精度的 MSVC 大括号初始化似乎违反了该标准
MSVC brace initialization with doubles appears to violate the standard?
看看这个简单的程序:
int main() {
float f2 = 7.2; // OK, with warning
float f3 = 7.199999809265137; // OK, no warning
float f4{ 7.2 }; // Fails
float f5{ 7.199999809265137 }; // OK, no warning
float f6 = { 7.2 }; // Fails
float f7 = { 7.199999809265137 }; // OK, no warning
}
使用默认选项(cl /W4
,版本19.00.23918)使用MSVC 2015编译时,我收到以下消息:
FloatTest.cpp(2): warning C4305: 'initializing': truncation from 'double' to 'float'
FloatTest.cpp(4): error C2397: conversion from 'double' to 'float' requires a narrowing conversion
FloatTest.cpp(4): warning C4305: 'initializing': truncation from 'double' to 'float'
FloatTest.cpp(6): error C2397: conversion from 'double' to 'float' requires a narrowing conversion
FloatTest.cpp(6): warning C4305: 'initializing': truncation from 'double' to 'float'
该程序在Clang 3.0-3.8和GCC 4.5.4-6.1.0(使用 http://melpon.org/wandbox 测试)中编译良好,仅对未使用的变量发出警告。此外,删除/注释掉f4
行和f6
会导致成功编译(行f2
只有一个警告)。
最初看起来 MSVC 只是告诉我 7.2 不能精确地表示为 float
,所以它是一个缩小的转换(这在大括号初始化中是非法的)。但是,标准(草案N3337)第8.5.4节注7是这样说的:
缩小转换是隐式转换...
- 从
long double
到double
或float
或从double
到float
,除非源是常量表达式并且转换后的实际值在可以表示的值范围内(即使不能精确表示)
强调我的。由于 7.2 在 float
表示的值范围内,根据标准,它转换为 float
不应该是缩小的转换。MSVC 在这里是错误的吗,我应该提交错误吗?
它看起来像一个错误,确实。对于解决方法,以下内容似乎可以消除 MSVC 2015 中的错误和警告。
#pragma float_control(precise, off, push)
float f2 = 7.2; // OK, with warning
//...
#pragma float_control(precise, pop)
如果使用 /fp:fast
编译器开关,则全局工作相同,尽管该开关与禁用 MS 语言扩展的/Za
不兼容。
有些浮点数可以用float
表示形式精确表示,有些则不能。如果数字可以用x / 2^y
的形式表示,其中x
是任何整数,y
是整数 23 或更小,则它适合。大多数十进制数不能以这种方式表示,作为二进制数,它们永远重复。 7.2
就是一个例子。
您可以通过将f
附加到每个数字来轻松解决此问题,以向编译器指示这是一个float
常量而不是double
。
float f4{ 7.2f };
相关文章:
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 标准::unordered_map 中的 std::array 的值初始化
- C++:带有大括号初始化列表的函数调用表达式 - 标准是否规定在单个元素列表的微不足道的情况下忽略大括号?
- 如何初始化一个标准::字符串数组?
- 直接初始化无符号短整型的标准行为
- 常量转发引用给出错误 C2440:"正在初始化":无法从"常量标准::字符串"转换为"常量标准::字符串 &&"
- 无法使用比较器初始化标准::函数
- 我需要初始化标准::字符串吗?
- 从另一个常量标准::映射初始化一个常量标准::映射的一部分
- 此代码中的数组初始化样式是什么?这是标准的吗?
- C 标准:通过复制返回以初始化无RVO的参考:是否有任何副本
- 复制省略用于列表初始化,它在标准中在哪里说明?
- 字符 [](c 字符串)的初始化标准
- 无法初始化标准::unique_ptr
- 特征库中标准偏差的逐列初始化和计算
- 在C++标准中哪里说必须初始化 const 内置类型变量的定义
- C 标准是否保证统一初始化是例外安全
- 标准的哪一部分决定了现场成员与初始化器列表的优先级
- C 标准中是否有任何计划来解决初始化器列表构造函数的不一致性
- 在C++中初始化布尔向量的标准方法是什么