简体   繁体   English

为什么没有clang警告从double到int的隐式转换,但是从long到int时呢?

[英]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 intint的转换可能或者工作或者可能是未定义的行为,具体取决于平台和值(唯一的保证是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. 另请注意,即使从doubleint转换也是合法且定义良好的(如果在边界内完成),即使在编译时可以看到精度损失,也不需要实现来警告它。 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 AnalyzerKlee项目-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.

相关问题 当double是常量时,为什么g ++ -Wconversion不会警告double转换为long int? - Why doesn't g++ -Wconversion warn about conversion of double to long int when double is constant? 为什么不将clang或gcc标记为从double到int的隐式转换? - Why doesn't clang or gcc flag this implicit conversion from double to int? 从long double转换为long long int - conversion from long double to long long int 为什么是对的隐式转换 <int64_t,int64_t> 配对 <int,int> 允许? - Why is implicit conversion from pair<int64_t,int64_t> to pair<int,int> allowed? 为什么将int提升为double而不是float以进行隐式转换 - Why is int promoted to double and not float for implicit conversion 从int到vector的隐式转换? - Implicit conversion from int to vector? 当涉及隐式转换时,为什么三元运算符将(...?int:unsigned long long)转换为int? - Why does the ternary operator turn (… ? int : unsigned long long) into int when an implicit conversion is involved? 为什么没有从 int 到 vector 的转换<double> ?</double> - Why is there no conversion from int to vector<double>? 如何在 C 和 C++ 中禁止从 int 到 double 的隐式转换? - How do I forbid an implicit conversion from int to double in C and C++? 在C / C ++中从double隐式转换为int64_t是什么 - What does implicit conversion from double to int64_t in C/C++
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM