8

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

int i;
(i) = 1;

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

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

赋值运算符应具有可修改的左值作为其左操作数。

赋值表达式在赋值后具有左操作数的值,但不是左值。

就我而言,有两个赋值表达式: 括号中的(i) = 1i。所以(i)应该是一个右值。

所以我的问题是: (i) = 1在这个 C 标准中是非法的吗?

4

3 回答 3

9

引用 n1570(出版前的最后一个 C11 标准草案):

6.5.1 主要表达方式(强调我的)

5 带括号的表达式是主要表达式。它的类型和值与无括号表达式的相同。如果不带括号的表达式分别是左值、函数指示符或 void 表达式,则它是左值、函数指示符或 void 表达式。

i是一个左值,所以根据上面的所以是(i)。为了回答你的问题,表达式(i) = 1是有效的 C。

于 2019-10-12T09:24:37.667 回答
0

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) = 1i。所以(i)应该是一个右值。

不,这是不正确的。(i) = 1是唯一的赋值表达式。有两个子表达式(一个带括号的标识符(i)和一个数字常量1)。

于 2019-10-12T19:46:54.467 回答
0

这个答案的灵感来自@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)一个左值。

于 2019-10-14T02:01:18.380 回答