复杂表达式的运算符优先级和求值顺序
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 是一个如上所述的左值)
我正在查看以下代码:
#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 是一个如上所述的左值)