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

Operator precedence and order of evaluation for complex expression

我正在查看以下代码:

#include <stdint.h>

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

  *pVal = i *= 10;
}

乍一看很明显,在从 foo() 返回之前,*pVal 将是 80 以及 i 的值。这确实是根据 godbolt.org:

发生的事情
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

但是从here查看运算符优先级后,=的优先级高于*=的优先级,所以*pVal的值似乎应为 8,i 的值应为 80...

我在这里错过了什么?

编辑:

除了 melpomene, there is also a nice Wikipedia page 的出色回答。

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

它们也是右结合的,因此 x = y *= z 正如预期的那样解析为 x = (y *= z)


如果 = 的优先级高于 *=,那么 x = y *= z 将解析为 (x = y) *= z,这将是一个硬错误,因为 = 不会' 产生一个左值(你不能赋值给赋值的结果)。如果 = 将其左操作数 return 作为左值,那么 (x = y) *= z 将具有未定义的行为,因为它在没有中间序列点的情况下修改了 x 两次。并且如果在内部分配之后有一个序列点,那么 (*pVal = i) *= 10 之后的变量的最终值将是 i = 8 (未修改)和 *pVal = 80.

Live demo(使用 Perl,它有一个 =,return 是一个如上所述的左值)