xto*_*ofl 8 c++ 64-bit visual-studio-2005
写这篇文章时:
1: inline double f( double arg ) {
2: return arg == 0.0 ? 0.0 : 1./arg;
3: }
4: const double d = f( 0.0 );
Run Code Online (Sandbox Code Playgroud)
微软Visual Studio 2005 64位编译器附带
line 4: warning C4723: potential divide by 0
Run Code Online (Sandbox Code Playgroud)
虽然你和我可以清楚地看到一个零分是永远不会发生的......
或者是吗?
Meh*_*ari 11
编译器无法静态分析所有代码路径,并始终考虑所有可能性.理论上,仅通过查看其源代码就可以完整地分析程序行为,这可以提供解决问题的解决方案,这是不可判定的.编译器具有一组有限的静态分析规则来检测规则.C++标准不要求编译器发出这种警告,所以,不.这不是一个错误.它更像是一个不存在的功能.
不,条件运算符不会计算两个参数.但是,如果编译器可以检测到这样的事情,通常会报告潜在的除零.标准占用约2页来描述该运算符的行为并非一无所获.
从N-4411:
5.16条件运算符
1条件表达式从右到左分组.第一个表达式在上下文中转换为bool(第4条).它被评估,如果是,则条件表达式的结果是第二个表达式的值,否则是第三个表达式的值.仅评估第二和第三表达式中的一个.在与第二或第三表达式相关联的每个值计算和副作用之前,对与第一表达式相关联的每个值计算和副作用进行排序.
另外,请注意:
3否则,如果第二个和第三个操作数具有不同的类型,并且具有(可能是cv-qualified)类类型,则尝试将每个操作数转换为另一个操作数的类型.
您引用的示例对于第二个和第三个表达式具有相同的类型 - 请放心,只会评估第一个表达式.
毫无疑问,这是一个明显的错误。
警告的目的不是警告程序中的所有分区。在任何合理的程序中这都太吵了。相反,其目的是在您需要检查参数时发出警告。在这种情况下,您确实检查了论证。因此,编译器应该注意到这一点,然后闭嘴。
这种功能的技术实现是通过用某些属性标记代码分支中的变量来完成的。最常见的属性之一是三态“Is null”。在分支之前,arg是一个外部变量并且arg [[Isnull]]是未知的。但检查后arg发现有两个分支。在第一个分支中arg [[Isnull]]是正确的。在第二个分支中arg [[Isnull]]是错误的。
现在,当涉及到生成被零除和空指针警告时,[[IsNull]应该检查该属性。如果为 true,则您将收到严重的警告/错误。如果未知,您应该生成上面显示的警告 - 一个潜在的问题,超出了编译器可以证明的范围。但在本例中,该[[isNull]]属性为 False。编译器通过与人类相同的形式逻辑,知道没有风险。
但是我们如何知道编译器在内部使用这样的[[Isnull]]属性呢?回想一下第一段:没有它,它必须要么总是警告,要么从不警告。我们知道它有时会发出警告,因此必须有一个[[IsNull]]属性。
| 归档时间: |
|
| 查看次数: |
1215 次 |
| 最近记录: |