这是来自creference:
赋值运算符的左操作数必须是一元(2 级非强制类型转换)表达式。
该参考页面有 2 次“级别”,即另一个是“优先级”。但优先级 1 有“函数调用”,优先级 2 有“sizeof”,两者都无法分配任何东西。
我可以理解“非强制类型转换”,因为强制类型转换可能会将左值转换为右值。
那么这个“2级”是什么意思呢?
这是来自creference:
赋值运算符的左操作数必须是一元(2 级非强制类型转换)表达式。
该参考页面有 2 次“级别”,即另一个是“优先级”。但优先级 1 有“函数调用”,优先级 2 有“sizeof”,两者都无法分配任何东西。
我可以理解“非强制类型转换”,因为强制类型转换可能会将左值转换为右值。
那么这个“2级”是什么意思呢?
对“level-2”的引用是对上表中 Precedence 列中标记为“2”的行的引用。
此“级别”是 cppreference.com 的发明;它不是 C 标准的一部分。(因此这也是 cppreference.com 不是一个好参考的原因之一。)C 标准没有按级别或表格指定优先级。优先级内置于语言的形式语法中。
在正式的 C 语法中,强制类型转换表达式是以下之一:
(
类型名称)
强制转换表达式一元表达式是以下之一:
++
一元表达式--
一元表达式&
、*
、+
、-
、~
或 之一!
sizeof
一元表达式sizeof
(
类型名称)
alignof
(
类型名称)
将这些与 cppreference.com 表进行比较,我们发现其优先级二级项是所有一元表达式的运算符(省略无运算符后缀表达式)加上强制类型转换运算符。因此,C 标准的一元表达式对应于 cppreference.com 的所有 2 级运算符(强制类型转换除外)。这就是 cppreference.com 使用“2 级非强制类型转换”的目的;取其 2 级运算符并删除强制类型转换,剩下“一元”运算符。(强制类型转换是“一元”的通用语言意义上的一元运算符,但它不包含在正式 C 语法的一元表达式标记中。这就是阻止
sizeof (int) * p
被解释为而不是sizeof ( (int *) p )
的原因(sizeof (int)) * p
,这在 cppreference.com 的注释 2 中提到但未解释。)cppreference.com 的声明“赋值运算符的左操作数必须是一元(2 级非强制类型转换)表达式”指的是,在 C 形式语法中,赋值表达式是以下之一:
因此,语法要求赋值运算符的左操作数是一元表达式。
这不是赋值运算符左操作数的唯一要求。C 2024 6.5.17.1 还规定:
这不是正式语法的一部分。它被单独陈述为一个约束。因此,赋值运算符的左操作数必须是一元表达式 ,并且必须是可修改的左值。