c++ - GCC 和 -W 转换

标签 c++ gcc language-lawyer

让我们编译下面的程序:

int main()
{
    uint16_t data = 0;
    data |= uint16_t(std::round(3.14f));
    return 0;
}

g++ -Wconversion prog.cpp

我们会收到警告:从“int”转换为“uint16_t {aka short unsigned int}”可能会改变它的值,但我在这里看不到隐式转换。

这种警告应该通过显式强制转换来消除,例如:

double d = 3.14;
float foo1 = d; // Warning
float foo2 = float(d); // No warning
float foo2 = static_cast<float>(d); // No warning

GCC 就在这里还是一个错误?

请注意,我的代码片段是最小的。例如,警告在以下情况下消失:

  • 3.14 中删除 f 后缀,即使其成为 double
  • 使用赋值代替 |=
  • 移除std::round
  • 缓存舍入结果:const auto r = uint16_t(std::round(3.14f));,然后将其或赋值给data

最佳答案

Is GCC right here or it's a bug?

由于行为与预期不符,我将其称为错误。

来自 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 维护者的疏忽。

关于c++ - GCC 和 -W 转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54195424/

相关文章:

c++ - 我们可以在 C++/VC++ 中访问 ODB++ 文件( PCB )吗?

c++ - 未找到 cxcore210d.dll

c++ - 我应该将哪个版本的 boost 与 c++ visual-studio-2005 一起使用?

c++ - Makefile vpath 不适用于头文件

c - GCC 使用 -O0 和 -O2 给出不同的数值结果

c++ - C++ 对象(标准定义)是否保留在内存映射文件中?

c++ - 为什么编译器不自动内联自由定义的函数?而是导致链接器错误

c++单例,堆栈溢出示例不起作用

c++ - gcc是否在带/不带大括号的单行中发出不同的输出

c++ - 分支中的 Lambda 未采用常量表达式 : Who is right?