C语言 评价顺序:未定义的行为?或编译器缺陷?

hec6srdp  于 2023-03-28  发布在  其他
关注(0)|答案(2)|浏览(116)

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

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

什么标准说:

  • 6.5.16赋值运算符 *

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

  • C运算符优先级规则 *

1.()
1.- ----

  1. ||和和
    对于问题案例:如果((a)||(B && c||d)== 1)编译器按以下顺序计算表达式并生成错误代码
    1.(B && c||d)--〉R1
    2.R1 == 1 --〉R2
    3.(a)||R2
    但是,编译器***会为以下情况生成正确的代码***

Case 1:.当没有关系'=='操作时

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

**Case 2:**逻辑或运算加括号时

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

**Case 3:**操作之间不使用括号

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

想知道问题案例是否福尔斯未定义行为类别。
致上,
麦克

z3yyvxxp

z3yyvxxp1#

相等运算符==的优先级高于逻辑或||运算符。因此,编译器是正确的,没有未定义的行为。
评价与以下内容相同:

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

fnatzsnv2#

这一点:

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 )

但编译器编译正确。只是不太明显的是,这意味着什么会发生在人类的头脑。

相关问题