标准 C 中的"(i) = 1"是否违法?



我正在编写一个遵循此标准的 C 编译器,如果我解析这样的语句:

int i;
(i) = 1;

我的编译器将报告一个错误,指出(i)是一个右值,不应该被分配。

我检查了代码和规则,发现: 在赋值表达式语义中:

赋值运算符的左侧应有一个可修改的左值 操作数。

赋值表达式在 赋值,但不是左值。

就我而言,有两个赋值表达式:(i) = 1i在括号中。所以(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) = 1i括弧。所以(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)是一个左值。

相关内容

最新更新