a++ 逻辑或 时,是用a判断还是a++判断


int main()
{
    int i = 0, a = 0, b = 2, c = 3, d = 4;
    i = a++ || ++b || d++;
    printf("%d\n%d\n%d\n%d\n%d\n", i, a, b, c, d);
    return 0;
}

我的意思就是 i 语句执行完了,a++才返回,还是说 i 语句走到 ||时,a就已经++了

我个人觉得这是未定义行为,得看编译器,我用gcc编译后用dbg反汇编结果如图所示(简单注释了一次):

img

img

以上是整个main函数的反汇编结果
可以简单分析一下:

img


上图部分是在定义变量

img


从上图中可以看到a先自增了,但是eax仍然是0!!!这意味着仍然采用的是自增前的a,然后有个跳转指令,但是这里不会跳转,因为eax&eax的结果是0(test是判断是否要执行第一个||),zf标志设为1,所以不会跳转

img

接下来从上图可以看到a自增完后b也自增了,cmp指令将b和0相减(这里的cmp指令就相当于判断b是否等于0,如果b还是0,说明第二个||运算也要执行),因为结果不为0(由于b=3)所以zf设为0,因此会发生跳转,第二个||被短路,d++不执行

img

跳转到以上位置后把1送入eax,这便是i的结果,为什么呢?因为前面说了,a虽然自增了,但是仍然使用的是自增前的a,所以相当于i=0||3=1,所以i=1
综上所述,虽然a先自增了,但参与运算的还是a自增前的值,而b则先自增再进行运算

逻辑与&&和逻辑或||运算在计算完左边子表达式之后有一个sequnece point,因此左边子表达式的所有side effect必须在这个squence point之前完成。
回到你的问题,a自增1的操作(side effect)是在计算第一项后就完成了。
也就是说在计算第一项时,a初始值是0,整个a++表达式的值是0,a的值变成1
由于第一项值为假,还需要接着计算第二项,b的初始值是2,b变成3,整个++b表达式值为3,非零为真,第三项就被短路了,所以d的值未变

https://en.cppreference.com/w/c/language/operator_logical#Logical_OR

Logical OR

The logical OR expression has the form

lhs || rhs
where

lhs - an expression of any scalar type
rhs - an expression of any scalar type, which is only evaluated if lhs compares equal to ​0​
The logical-OR operator has type int and the value 1 if either lhs or rhs compare unequal to zero. It has value ​0​ otherwise (if both lhs and rhs compare equal to zero).

There is a sequence point after the evaluation of lhs. If the result of lhs compares unequal to zero, then rhs is not evaluated at all (so-called short-circuit evaluation)

https://en.cppreference.com/w/c/language/eval_order