我正在编写一个遵循这个标准的 C 编译器,如果我解析这样的语句:
int i;
(i) = 1;
我的编译器会报告一个错误,指出这(i)是一个右值,不应该是可分配的。
我检查了代码和规则,发现:在赋值表达式语义中:
赋值运算符应具有可修改的左值作为其左操作数。
赋值表达式在赋值后具有左操作数的值,但不是左值。
就我而言,有两个赋值表达式:
括号中的(i) = 1和i。所以(i)应该是一个右值。
所以我的问题是:
(i) = 1在这个 C 标准中是非法的吗?
我正在编写一个遵循这个标准的 C 编译器,如果我解析这样的语句:
int i;
(i) = 1;
我的编译器会报告一个错误,指出这(i)是一个右值,不应该是可分配的。
我检查了代码和规则,发现:在赋值表达式语义中:
赋值运算符应具有可修改的左值作为其左操作数。
赋值表达式在赋值后具有左操作数的值,但不是左值。
就我而言,有两个赋值表达式:
括号中的(i) = 1和i。所以(i)应该是一个右值。
所以我的问题是:
(i) = 1在这个 C 标准中是非法的吗?
引用 n1570(出版前的最后一个 C11 标准草案):
6.5.1 主要表达方式(强调我的)
5 带括号的表达式是主要表达式。它的类型和值与无括号表达式的相同。如果不带括号的表达式分别是左值、函数指示符或 void 表达式,则它是左值、函数指示符或 void 表达式。
i是一个左值,所以根据上面的所以是(i)。为了回答你的问题,表达式(i) = 1是有效的 C。
StoryTeller 已经在标准中解释了为什么对于您的示例,表达式(i)仍然是左值,但我相信您无缘无故地挂在规范上,所以请允许我尝试解决您的问题。
我检查了代码和规则,发现:在赋值表达式语义中:
赋值运算符应具有可修改的左值作为其左操作数。
赋值表达式在赋值后具有左操作数的值,但不是左值。
整个引用是指整个赋值表达式,而不是 lhs 或 rhs。
“赋值运算符应有一个可修改的左值作为其左操作数。” 声明 lhs 必须是可修改的左值。
“赋值表达式在赋值后具有左操作数的值,但不是左值。” 声明整个赋值表达式本身作为结果具有 lhs 的值,并且本身是一个右值。
所以以下都是真的:
int i;
i <- modifiable lvalue
(i) = 1;
(i) <- modifiable lvalue (per StoryTeller's answer)
1 <- rvalue
((i) = 1) <- rvalue
为什么这很重要?考虑以下:
int i = 0, j = 0, k = 0;
i = j = k = 1;
// parsed as `i = (j = (k = 1))`
// the expression `k = 1` has the value `1` and is an rvalue
// the expression `j = (k = 1)` has the value `1` and is an rvalue
(i = 2) = 3;
// is invalid, the expression `i = 2` is an rvalue, but it may not be the lhs of the assignment
就我而言,有两个赋值表达式:括号中的
(i) = 1和i。所以(i)应该是一个右值。
不,这是不正确的。(i) = 1是唯一的赋值表达式。有两个子表达式(一个带括号的标识符(i)和一个数字常量1)。
这个答案的灵感来自@Eric Postpischil。
a 的产生assignment-expression是:
<assignment-expression> ::= <conditional-expression>
| <unary-expression> <assignment-operator> <assignment-expression>
在标准中,assignment expression具体是指带有赋值运算符的表达式。所以:
<conditional-expression> is not an assignment expression
<unary-expression> <assignment-operator> <assignment-expression> is an assignment expresssion
所以规则:
赋值表达式在赋值后具有左操作数的值,但不是左值。
只适合生产<unary-expression> <assignment-operator> <assignment-expression>,不适合<conditional-expression>
在示例(i) =1中,i是一个<assignment-expression>但不是一个assignment expression,它是一个<conditional-expression>所以它是一个左值所以它是(i)一个左值。