[英]Why doesn't clang warn about implicit conversion from double to int, but do it when from long to int?
In the following code: 在以下代码中:
#include <iostream>
int main()
{
const long l = 4294967296;
int i = l;
return i; //just to silence the compiler
}
the compiler warns about implicit conversion (using -Wall and -std=c++14) as following: 编译器警告隐式转换(使用-Wall和-std = c ++ 14)如下:
warning: implicit conversion from 'const long' to 'int' changes value from 4294967296 to 0 [-Wconstant-conversion]
which is ok. 没关系。 But there is no warning if the conversion is from double to int, as in the following code:
但是如果转换是从double到int,则没有警告,如下面的代码所示:
#include <iostream>
int main()
{
const double d = 4294967296.0;
int i = d;
return i; //just to silence the compiler
}
Why the compiler reacts differently in these situations? 为什么编译器在这些情况下会有不同的反应?
Note 1: clang version is 3.6.2-svn240577-1~exp1 注1:clang版本为3.6.2-svn240577-1~exp1
Note 2: I've tested it with many others versions of gcc, clang and icc thanks to Compiler Explorer (gcc.godbolt.org). 注2:我已经使用Compiler Explorer(gcc.godbolt.org)测试了许多其他版本的gcc,clang和icc。 So all tested versions of gcc (with exception of 5.x) and icc threw the warning.
因此,所有测试版本的gcc(除了5.x)和icc都会发出警告。 No clang version did it.
没有clang版本做到了。
The conversion from double
to an integer type changes the value "by design" (think to 3.141592654
converted to an int
). 从
double
到整数类型的转换会更改“按设计”的值(想想转换为int
3.141592654
)。
The conversion from long int
to int
instead may or work or may be undefined behavior depending on the platform and on the value (the only guarantee is that an int
is not bigger than a long int
, but they may be the same size). 从
long int
到int
的转换可能或者工作或者可能是未定义的行为,具体取决于平台和值(唯一的保证是int
不大于long int
,但它们可能是相同的大小)。
In other words the problems in the conversions between integer types are incidental artifacts of the implementation, not by-design decisions. 换句话说,整数类型之间的转换中的问题是实现的偶然工件,而不是设计决策。 Warning about them is better especially if it can be detected at compile time that something doesn't work because of those limitations.
关于它们的警告更好,特别是如果在编译时可以检测到由于这些限制而无法正常工作。
Note also that even conversion from double
to int
is legal and well defined (if done within boundaries) and an implementation is not required to warn about it even when the loss of precision can be seen at compile time. 另请注意,即使从
double
到int
转换也是合法且定义良好的(如果在边界内完成),即使在编译时可以看到精度损失,也不需要实现来警告它。 Compilers that warn too much even when the use could be meaningful can be a problem (you just disable warnings or even worse get the habit of accepting a non-clean build as normal). 即使在使用可能有意义的情况下过多警告的编译器也可能是一个问题(您只是禁用警告,甚至更糟糕的是习惯于接受非正常构建)。
These implicit conversion rules may add up with other C++ wrinkles getting to truly odd-looking and hard to justify behaviors like: 这些隐式转换规则可能与其他C ++皱纹相结合,变得真正奇怪且难以证明行为如下:
std::string s;
s = 3.141592654; // No warnings, no errors (last time I checked)
Don't try to use too much logic with C++. 不要试图用C ++过多的逻辑。 Reading specs works better.
阅读规格效果更好。
Well, by reading this great article named "What Every C Programmer Should Know About Undefined Behavior", specially part #3/3, at LLVM Project Blog , written by Chris Lattner - the main author of LLVM - I could understand better the Clang's Approach to Handling Undefined Behavior . 好吧,通过阅读这篇名为“每个C程序员应该知道的未定义行为的内容”的文章,特别是第3部分,在LLVM项目博客上 ,由LLVM的主要作者Chris Lattner撰写 - 我可以更好地理解Clang的方法处理未定义的行为 。
So, in order to guarantee your strong appeal for optimization and time economy - "ultimate performance" - 因此,为了保证您对优化和时间经济的强烈吸引力 - “最终表现” -
Keep in mind though that the compiler is limited by not having dynamic information and by being limited to what it can without burning lots of compile time.
请记住,虽然编译器受限于没有动态信息,并且受限于它可以在不浪费大量编译时间的情况下。
Clang doesn't run all related undefined behavior checks by default, 默认情况下,Clang不会运行所有相关的未定义行为检查,
Clang generates warnings for many classes of undefined behavior (including dereference of null, oversized shifts, etc) that are obvious in the code to catch some common mistakes.
Clang为许多类的未定义行为(包括取消引用null,超大移位等)生成警告,这些行为在代码中很明显,可以捕获一些常见错误。
instead of this, Clang and LLVM provides tools like Clang Static Analyzer , Klee project , and the -fcatch-undefined-behavior
(now UndefinedBehaviorSanitizer - UBSan - ) to avoid these possible bugs. 而不是这样,Clang和LLVM提供了诸如Clang Static Analyzer , Klee项目和
-fcatch-undefined-behavior
(现在是UndefinedBehaviorSanitizer - UBSan - )之类的工具来避免这些可能的错误。
By running UBSan in the presented code, clang++
with the following argument -fsanitize=undefined
the bug will be catched as following: 通过在提供的代码中运行UBSan ,使用以下参数
clang++
-fsanitize=undefined
,将-fsanitize=undefined
如下错误:
runtime error: value 4.29497e+09 is outside the range of representable values of type 'int'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.