运算符优先级和复杂表达式的求值顺序

时间:2019-01-09 10:25:24

标签: c operator-precedence

我正在查看以下代码:

#include <stdint.h>

void foo(uint32_t *pVal)
{
  uint32_t i = 8;

  *pVal = i *= 10;
}

乍一看,很明显,从foo()返回之前,*pVal等于i的值是80。根据{{​​3}},确实发生了这种情况:

foo:                                    # @foo
        push    rbp
        mov     rbp, rsp
        mov     qword ptr [rbp - 8], rdi
        mov     dword ptr [rbp - 12], 8
        imul    eax, dword ptr [rbp - 12], 10
        mov     dword ptr [rbp - 12], eax
        mov     rdi, qword ptr [rbp - 8]
        mov     dword ptr [rdi], eax
        pop     rbp
        ret

但是,从godbolt.org检查运算符优先级之后,=的优先级高于*=的优先级,因此看来*pVal的值应为8,而i的值应为80 ...

我在这里想念什么?

编辑

除了here的出色回答外,还有一个不错的melpomene

1 个答案:

答案 0 :(得分:4)

您链接到的表以相同的优先级显示了所有赋值运算符(包括=*=):

它们也是正确的关联对象,因此x = y *= z解析为x = (y *= z),符合预期。


如果=的优先级高于*=,则x = y *= z将解析为(x = y) *= z,这将是一个很难的错误,因为=不会产生一个左值(不能分配给赋值的结果)。如果=确实将其左操作数作为左值返回,则(x = y) *= z将具有未定义的行为,因为它两次修改了x而没有中间的顺序点。并且如果内部分配之后有一个序列点,则(*pVal = i) *= 10之后的变量的最终值为i = 8(未修改)和*pVal = 80

Live demo(使用Perl,它有一个=,它如上所述返回左值)