代码之家  ›  专栏  ›  技术社区  ›  xtofl Adam Rosenfield

条件运算符是否应计算所有参数?

  •  8
  • xtofl Adam Rosenfield  · 技术社区  · 15 年前

    写这篇文章时:

    1: inline double f( double arg ) {
    2:    return arg == 0.0 ? 0.0 : 1./arg;
    3: }
    4: const double d = f( 0.0 );
    

    microsoft visual studio 2005 64位编译器随附

    line 4: warning C4723: potential divide by 0
    

    而你我都能清楚地看到,一个除以零的div是 即将发生的事。。。

    还是这样?

    8 回复  |  直到 15 年前
        1
  •  4
  •   MSalters    15 年前

    毫无疑问,这是一个明显的错误。

    arg 是一个外部变量,并且 arg [[Isnull]] 这是未知的。但是在检查之后 arg 有两个分支。在第一个分支中 arg[[Isnull]] 这是错误的。

    [[IsNull] 属性应该被选中。如果为true,则表示出现严重警告/错误。如果未知,您应该生成上面显示的警告-这是一个潜在的问题,超出了编译器可以证明的范围。但在这种情况下 [[isNull]]

    但是,我们如何知道编译器正在使用这样的 [[Isnull]] [[IsNull]]

        2
  •  11
  •   Mehrdad Afshari    15 年前

    编译器无法静态分析所有代码路径,并始终考虑所有可能性。从理论上讲,仅仅通过查看程序的源代码就可以对程序行为进行完整的分析,从而解决无法确定的停止问题。编译器有一组有限的静态分析规则来检测规则。C++标准不要求编译器发出这样的警告,所以,不,它不是bug。它更像是一个不存在的功能。

        3
  •  7
  •   Community CDub    4 年前

    否,条件运算符不计算两个参数。然而,如果编译器能够检测到这种情况,通常会报告一个被零除的可能性。该标准占用约2页来描述该操作员的行为并非毫无意义。

    从N-4411:

    5.16条件运算符

    条件表达式组 从右到左。第一个表达是 4). 它被评估,如果它是真的, 表达式是第二个表达式的值 第二和第三个表达式是 表达式在每个 价值计算与副作用 表情。

    此外,请注意:

    否则,如果第二个和第三个 操作数具有不同的类型,并且 任何一方都有(可能是合格简历) 将每个操作数转换为

        4
  •  3
  •   Adrien Plisson    15 年前

    将生成分区的代码,因此会发出警告。但是,当你需要的时候,树枝永远不会被拿走 arg 是0,因此它是安全的。

        5
  •  3
  •   Gorpik    15 年前

    浮点数的运算符==不安全(即,由于舍入问题,您不能信任它)。在这种特定情况下,它实际上是安全的,因此您可以忽略警告,但编译器不会基于在一般情况下其结果有些不可预测的运算符进行此类分析。

        6
  •  3
  •   Kirill V. Lyadvinsky    15 年前

    条件运算符不应计算所有参数。但我相信你可以 arg 几乎等于0,所以 arg == 0.0 false 但是 1./arg

    顺便说一下,Visual C++ 2008没有给出这样的警告。

        7
  •  0
  •   peterchen    15 年前

    除其他注释外:警告由编译器生成,死分支由优化器删除,优化器稍后运行-甚至可能在链接阶段。

        8
  •  0
  •   Stack Overflow is garbage    15 年前

    __assume 关键词。我不确定你是否能把它和条件运算符联系起来。否则的话

    if (arg == 0.0){
      return 0.0;
    }
    else {
    __assume(arg != 0.0);
      return 1./arg;
    }
    

    也许值得一试。当然,也可以在执行此功能时,使用适当的 #pragma