我正在编写一个遵循此标准的 C 编译器,如果我解析这样的语句:
int i;
(i) = 1;
我的编译器将报告一个错误,指出(i)
是一个右值,不应该被分配。
我检查了代码和规则,发现: 在赋值表达式语义中:
赋值运算符的左侧应有一个可修改的左值 操作数。
赋值表达式在 赋值,但不是左值。
就我而言,有两个赋值表达式:(i) = 1
和i
在括号中。所以(i)
应该是一个右值。
所以我的问题是: 是 在这个C标准中(i) = 1
违法的吗?
引用n1570(发布前的最后 C11 标准草案(:
6.5.1 主要表达式(强调我的(
5 括号表达式是主要表达式。它的类型 和值与不带括号的表达式相同。 它是左值、函数指示符或 void 表达式,如果 无括号表达式分别是左值、函数 指示符或空表达式。
i
是一个左值,所以根据上述内容,(i)
.为了回答您的问题,表达式(i) = 1
是有效的 C。
StoryTeller 已经解释了为什么在您的示例中,表达式(i)
仍然是一个左值,但我相信您无缘无故地挂在规范上,所以请允许我尝试解决您的问题。
我检查了代码和规则,发现这个:在分配中 表达式语义:
赋值运算符的左侧应有一个可修改的左值 操作数。
赋值表达式在 赋值,但不是左值。
整个引文指的是整个赋值表达式,而不是 lhs 或 rhs。
"赋值运算符应具有可修改的左操作数",指出 LHS 必须是可修改的右值。
"赋值表达式在赋值后具有左操作数的值,但不是左值",指出整个赋值表达式本身作为结果具有 LHS 的值,并且本身是一个 rvalue。
所以以下都是真的:
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。
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>
所以它是一个lvaule,所以(i)
是一个左值。