看看这个简单的程序:
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
,所以它是一次缩小转换(在大括号初始化中是非法的)。然而,标准(draft N3337),第8.5.4节,注7说:
缩小转换是一种隐式转换...
- 从
long double
到double
或float
,或者从double
到float
,除非源是常数表达式并且转换后的实际值在可表示值的范围内(即使不能完全表示)
重点是我的。由于7.2在float
可表示的值范围内,根据标准,其转换为float
不应是一次缩小转换。MSVC这里错了吗?我应该提交一个错误报告吗?
/W4
。 - Richard Crittenf
呢? - Chris Beck