最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

level-2 expression in C - Stack Overflow

programmeradmin0浏览0评论

This is from creference:

Assignment operators' left operands must be unary (level-2 non-cast) expressions.

That reference page has 2 occurences of "level", i.e. the other is "precedence level". But precedence level 1 has "Function call" and precedence level 2 has "sizeof" which are both can't be assigned something to.

I can understand "non-cast" because cast may convert lvalue to rvalue.

Then what does that "level-2" mean?

This is from creference:

Assignment operators' left operands must be unary (level-2 non-cast) expressions.

That reference page has 2 occurences of "level", i.e. the other is "precedence level". But precedence level 1 has "Function call" and precedence level 2 has "sizeof" which are both can't be assigned something to.

I can understand "non-cast" because cast may convert lvalue to rvalue.

Then what does that "level-2" mean?

Share Improve this question asked Mar 30 at 11:07 An5DramaAn5Drama 7311 gold badge4 silver badges13 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 6

The reference to “level-2” is a reference to the row labeled “2” in the Precedence column in the preceding table.

This “level” is an invention of cppreference; it is not part of the C standard. (And so it is one reason cppreference is not a good reference.) The C standard does not specify precedences by levels or a table. Precedence is built into the formal grammar of the language.

In the formal C grammar, a cast-expression is one of:

  • unary-expression
  • ( type-name ) cast-expression

A unary-expression is one of:

  • postfix-expression
  • ++ unary-expression
  • -- unary-expression
  • unary-operator cast-expression, where unary-operator is one of &, *, +, -, ~, or !
  • sizeof unary-expression
  • sizeof ( type-name )
  • alignof ( type-name )

Comparing these to the cppreference table, we see its precedence level two items are all the operators of a unary-expression (omitting the operator-less postfix-expression) plus the cast operator. Therefore, the C standard’s unary-expression corresponds to all of cppreference’s level-2 operators except the cast. That is what cppreference is getting at with “level-2 non-cast”; taking its level-2 operators and removing the cast leaves the “unary” operators. (Cast is a unary operator,1 but it is not included in the unary-expression token in the formal C grammar. This is what prevents sizeof (int) * p from being interpreted as sizeof ( (int *) p ) instead of (sizeof (int)) * p, which is mentioned, but not explained, in cppreference’s note 2.)

cppreference’s statement that “Assignment operators' left operands must be unary (level-2 non-cast) expressions” refers to the fact that, in the C formal grammar, an assignment-expression is one of:

  • conditional-expression
  • unary-expression assignment-operator assignment-expression

Thus, the grammar requires that the left operand of an assignment operator be a unary-expression.

This is not the only requirement on the left operand of an assignment operator. C 2024 6.5.17.1 also states:

An assignment operator shall have a modifiable lvalue as its left operand.

This is not part of the formal grammar. It is stated separately as a constraint. So the left operand of an assignment operator must be a unary-expression and it must be a modifiable lvalue.

Footnote

1 Per Kernighan and Ritchie, The C Programming Language (second edition), 1988, page 45: “Finally, explicit type conversions can be forced (‘coerced’) in any expression, with a unary operator called a cast.”

发布评论

评论列表(0)

  1. 暂无评论