让我们编译以下程序:
int main()
{
uint16_t data = 0;
data |= uint16_t(std::round(3.14f));
return 0;
}
with g++ -Wconversion prog.cpp
我们会得到warning: conversion to ‘uint16_t {aka short unsigned int}’ from ‘int’ may alter its value
,但我在这里看不到隐式转换。
这种警告应该通过显式强制转换来消除,例如:
double d = 3.14;
float foo1 = d; // Warning
float foo2 = float(d); // No warning
float foo2 = static_cast<float>(d); // No warning
GCC 就在这里还是一个错误?
请注意,我的片段很小。例如,在以下情况下警告消失:
- 去除
f
后缀来自3.14
,即做到double
- 使用赋值代替
|=
- remove
std::round
- 缓存舍入结果:
const auto r = uint16_t(std::round(3.14f));
,然后或将其分配给data
.
GCC 就在这里还是一个错误?
由于行为与预期不符,我将其称为错误。
From https://godbolt.org/z/aSj--7 https://godbolt.org/z/aSj--7,看来在GCC眼里,data |= uint16_t(std::round(3.14f))
被翻译为
(void) (data = TARGET_EXPR <D.2364, (uint16_t) round (3.1400001049041748046875e+0)>;, data | NON_LVALUE_EXPR <D.2364>;)
(TARGET_EXPR
代表一个临时对象。D.2364
是内部变量名。)
将 GCC 的内部语言翻译回 C++,我们将得到
data = (temp = (uint16_t) round (3.14e+0), data | temp)
由于逗号表达式的 LHS 不会影响 RHS,因此这应该和data = data | temp
。然而,GCC 对前者发出警告,但不对后者发出警告,这不太可能是故意的。因此我认为这是 GCC 维护者的疏忽。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)