我正在查看以下代码:
#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 ...
我在这里想念什么?
编辑:
答案 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,它有一个=
,它如上所述返回左值)