C 复杂表达式的运算符优先级和求值顺序
我正在查看以下代码:C 复杂表达式的运算符优先级和求值顺序,c,operator-precedence,C,Operator Precedence,我正在查看以下代码: #include <stdint.h> void foo(uint32_t *pVal) { uint32_t i = 8; *pVal = i *= 10; } 但是,在从检查运算符优先级后,=的优先级高于*=的优先级,因此似乎*pVal的值应为8,i的值应为80 我错过了什么 编辑: 除了由给出的很好的答案外,还有一个很好的答案。您链接到的表显示了相同优先级的所有赋值运算符(包括=和*=):14 它们也是右关联的,因此正如预期的那样,x=y*=
#include <stdint.h>
void foo(uint32_t *pVal)
{
uint32_t i = 8;
*pVal = i *= 10;
}
但是,在从检查运算符优先级后,=
的优先级高于*=
的优先级,因此似乎*pVal
的值应为8,i
的值应为80
我错过了什么
编辑:
除了由给出的很好的答案外,还有一个很好的答案。您链接到的表显示了相同优先级的所有赋值运算符(包括
=
和*=
):14
它们也是右关联的,因此正如预期的那样,x=y*=z
解析为x=(y*=z)
如果
=
的优先级高于*=
,则x=y*=z
将解析为(x=y)*=z
,这将是一个硬错误,因为=
不会产生左值(您无法分配给赋值的结果)。如果=
确实将其左操作数作为左值返回,则(x=y)*=z
将具有未定义的行为,因为它在没有插入序列点的情况下修改了x
两次。如果内部赋值后有一个序列点,(*pVal=i)*=10
后变量的最终值将是i=8
(未修改)和*pVal=80
(使用Perl,它有一个返回左值的
=
,如上所述)@AlexLop。它还说第一列是优先级。表中同一行中的所有行具有相同的优先级。@AlexLop。它是从上到下列出的“优先级”列,1
是最高的,15
是最低的。同一级别上的所有运算符都具有相同的优先级。谢谢您的回答。我很高兴我只是误解了图表。请注意,链接的优先表有错误(他们将cast运算符放在错误的组中,有17个组而不是15个组等)。大多数这样的表都有错误,因为C标准没有列出这样的表。有一次,我厌倦了所有这些糟糕的桌子,并试图自己做一张。但是,由于它是一个屏幕截图,所以格式很糟糕:/@Lundin我认为您的表是错误的,因为它将强制类型转换放在了错误的组中。强制转换是一元(前缀)运算符,不能有具有不同优先级的前缀运算符。此外,主表达式不是运算符。@melpomene一元运算符和强制转换在标准中属于不同的组(在C17草案6.5 p3中指定的分组),强制转换具有较低的优先级。@melpomene C标准C17 6.5.4是具有强制转换运算符的组(只有一个)。如语法所示,它的优先级低于一元运算符。我的表遵循标准的组和语法,与cppreference中的表不同。@Lundin我看到的是cast expression:unary expression |…
和unary expression:unary operator cast expression |…
,因此它们是相互递归的,且优先级都不高于另一个。他们在不同的组中的唯一原因是一种语法黑客,用sizeof
消除歧义:根据语法,sizeof(int)+0
明确地解析为(sizeof(int))+0
,而不是sizeof((int)+0)
(也就是说,这个表达式中没有强制转换)。
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