为什么 g++ 或 clang 在通过将非常量变量分配给较小类型的变量来截断非常量变量时不引发警告
Why does not g++ or clang elicit a warning when truncating a non-const variable by assigning it to a variable of smaller type?
当变量 x 在下面的代码片段中声明为常量时,clang 2.9 和 g++ 4.1.2 都会生成警告。但是,当 const 被删除时,就像它在代码片段中一样,即使使用以下我所知道的最严格的参数执行,编译器也不会生成警告:"-Wall -Wextra -pedantic -ansi"
为什么编译器不会推断并报告相同的警告,因为 x 不是易失性的,并且在类型转换之前不可能修改?
#include <iostream>
int main(int argc, char **argv)
{
unsigned int x = 1000;
const unsigned char c = x;
const unsigned int x_ = c;
std::cout << "x=" << x << " x_=" << x_ << std::endl;
return 0;
}
使用 const 无符号 int x = 1000; g++ 提供消息"警告:大整数隐式截断为无符号类型"和 clang "警告:从 'const unsigned int' 到 'const unsigned char' 的隐式转换将值从 1000 更改为 232 [-Wconstant-conversion]"。
有没有办法在不手动检查代码或依赖正确设计的单元测试的情况下自动检测这种情况?
对于 GCC,添加标志-Wconversion
,您将收到所需的警告。这不是-Wall
的一部分,因为如此多的代码只是忽略了这些类型的东西。我总是打开它,因为它发现否则很难调试缺陷。
如果它是一个常量,编译器可以看到它的值并警告截断。如果它不是常量,则不能,尽管进行了初始化。这:
const unsigned int x = 1000;
const unsigned char c = x;
相当于:
const unsigned char c = 1000;
我已经用 -O3 -fdump-tree-vrp 运行了 gcc,我在转储中看到的是:
std::__ostream_insert<char, std::char_traits<char> > (&cout, &"x="[0], 2);
D.20752_20 = std::basic_ostream<char>::_M_insert<long unsigned int> (&cout, 1000);
std::__ostream_insert<char, std::char_traits<char> > (D.20752_20, &" x_="[0], 4);
D.20715_22 = std::basic_ostream<char>::_M_insert<long unsigned int> (D.20752_20, 232);
即它只是在 cout 语句中内联常量 1000 和 232!
如果我用 -O0 运行它,它不会转储任何东西,尽管有 -ftree-vrp 和 -ftree-ccp 开关。
似乎 gcc 在发出警告之前内联常量......
相关文章:
- 用C++中的一个变量定义一个常量
- 通过多个头文件使用常量变量
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 非常量变量只读位置的赋值
- 多个"常量引用"变量可以共享同一个内存吗?
- 使用大量已知常量变量的正确方法
- 常量成员函数中成员变量的类型
- 无法在具有常量变量大小的类中创建堆栈分配数组
- 错误:constexpr 变量'struct2Var'必须由常量表达式初始化
- 这些语句是否等效(静态变量、常量变量和泛型)
- 如何将变量内容常量转换为 std::array 的大小?
- 我应该使我的局部变量常量还是可移动的
- 为什么我可以改变常量对象中的成员变量,这是返回常量对象函数的结果?
- 对全局变量的非常量引用的初始化无效
- 如何在 C++ 中的 wcstok 中使用常量 WCHAR* 变量?
- 将 static_cast<int>(-15) 分配给静态常量字符类型变量
- 全局变量/常量的替代方案
- 为什么首选 if( 常量 == 变量 ) 而不是 if ( 变量 == 常量 )
- 在c++中声明一个变量常量有什么意义