【问题标题】:Why does g++ 4.8.1 issue a conversion warning为什么g++ 4.8.1会发出转换警告
【发布时间】:2014-01-16 13:56:03
【问题描述】:

当我以这种方式用 g++ 4.8.1 (64bit) 编译下面的代码时:

$ g++ -Wconversion -o main main.cpp

我得到这个结果:

main.cpp: In function ‘int main()’:
main.cpp:12:20: warning: conversion to ‘int’ from ‘long unsigned int’ may alter its value [-Wconversion]
   int i = sizeof(x)/sizeof(x[0]);
                    ^

我的期望是编译器应该能够在编译时评估表达式。如果你用纯 c 编写一个类似的程序,gcc 就像一个魅力。

这是否应该被认为是g++中的一个bug(例如clang++没有这个问题)?

如果您将有问题的行更改为:

char c = 0x10000000/0x1000000;

那么编译器不会抱怨。这表明在生成警告之前会进行一些持续评估。

main.cpp:

#include <iostream>

struct foo {
  int a;
  int b;
};

foo x[50];

int main()
{
  int i = sizeof(x)/sizeof(x[0]);
  std::cout << i << std::endl;

  return 0;
}

【问题讨论】:

  • 只是没有优化吗?试试-O2,它应该在编译时评估它。
  • 我确实在 4.8 中也收到了警告,但在 4.9 版中我没有(大约一周前的 GCC 来源),所以我认为 GCC 开发人员确实认为这是一个错误并且有已经修好了。

标签: c++ gcc


【解决方案1】:
 int i = sizeof(x)/sizeof(x[0]);
 //int <-- std::size_t <-- std::size_t / std::size_t

表达式sizeof(x)/sizeof(x[0]) 的类型是std::size_t,在您的机器上是unsigned long int。因此,如果源大于目标,则从这种类型转换为int 会导致数据丢失。

不过,我同意在您的情况下,如果编译器 实际上 计算该值,不会实际数据丢失,但我想它适用 -Wconversion实际计算之前。

【讨论】:

  • 除法是问题所在,因为它是转换为int 的操作的结果。该部门本身是安全的。
  • 任何人都可以提供一个标准引用,说明在编译时评估表达式可以忽略标准中的其他规则吗?我只能找到一个注释,浮点运算可以给出不同的结果,因为没有指定浮点精度。为什么本题的转换不受标准转换规则的约束?
  • @sftrabbit:我的意思是 RHS 不能溢出int,因为它的值是40(数组的大小),它是编译时常量。因此,即使从类型的角度来看,警告是有意义的,但从实际值的角度来看(编译器已知)是多余的。
  • @Nawaz 哦,这很有道理。好点子。尽管编译器时评估在某种程度上不受某些规则的约束,但我确实不断看到一些建议。
  • 这可能只是编译器的警告触发器不够复杂,在 可能 产生问题(即使在这里明显不是问题)。
【解决方案2】:

sizeof() 返回您 std::size_t 而不是 int!所以将它转换或将i 声明为std::size_t

 std::size_t i = sizeof(x)/sizeof(x[0]);

【讨论】:

    猜你喜欢
    • 2011-06-25
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 2019-05-06
    • 2014-01-29
    • 2015-12-11
    • 2017-01-12
    • 2011-12-05
    相关资源
    最近更新 更多