评估顺序:未定义的行为?或编译器缺陷?

时间:2016-07-29 09:56:21

标签: c undefined-behavior ansi unspecified-behavior

我从C编译器得到以下测试代码的asm代码错误。 这是由于未定义的行为吗?

void SimulatedTest(void)
{                                   
    if ( (a) || (b && c || d) == 1 )
    {
        i = 2;
    }
    else
    {
        i = 4;
    }
}

标准是什么:

6.5.16分配操作员

  

未指定操作数的评估顺序。如果尝试   用于修改赋值运算符的结果或访问它   在下一个序列点之后,行为未定义

C运营商优先规则

  
      
  1. ()
  2.   
  3. ==
  4.   
  5. || &安培;&安培;
  6.   

对于问题情况:if((a)||(b&& c || d)== 1) 编译器按以下顺序计算表达式并生成错误的代码

  

1.(b&& c || d) - > R1

     

2.R1 == 1 - > R2

     

3.(a)|| R2

然而编译器 为以下情况生成正确的代码

情况1:即可。如果没有关系' =='操作

if ( (a) || (b && c || d) )//compiler generates expected code

案例2:为逻辑OR操作添加括号

if ( ((a) || (b && c || d)) == 1 )//compiler generates expected code

案例3:在操作之间没有使用括号

if ( a || b && c || d == 1 )//compiler generates expected code

想知道问题案例是否属于未定义的行为类别。

此致

的Mac

2 个答案:

答案 0 :(得分:7)

等式运算符==的优先级高于逻辑或||运算符。因此编译器是正确的,并且没有未定义的行为。

评估与:

相同
a || ( ( b && c || d ) == 1 )

答案 1 :(得分:0)

此:

 if ( (a) || (b && c || d) == 1 )

||的结果与一个永远不是你想做的整数进行比较。

鉴于逻辑运算符的优先顺序并不总是人们所期望的,通常最安全的是放入括号以使事物更清晰,因此

 if ( (a) || ((b && c) || d) == 1 )

 if ( (a) || (b && (c || d)) == 1 )

处理&&||

并且取决于你期望==与之比较(如果你真的想要这样做,我怀疑)

 if ( (a) || ((b && c || d) == 1) )

 if ( ((a) || (b && c || d)) == 1 )

但是编译器正在编译。对于人类思维来说,发生什么事情并不是非常明显。