`(I) = 1` é ilegal no padrão C?


8

Estou escrevendo um compilador C que segue esse padrão e se eu analisar declarações como esta:

int i;
(i) = 1;

meu compilador relatará um erro que indica que (i)é um rvalue e não deve ser atribuído.

Eu verifiquei o código e as regras e descobri o seguinte: na atribuição semântica da expressão:

Um operador de atribuição deve ter um valor modificável como seu operando esquerdo.

Uma expressão de atribuição possui o valor do operando esquerdo após a atribuição, mas não é um valor l.

No meu caso, existem duas expressões de atribuição: (i) = 1e ientre parênteses. Portanto, (i)deve ser um rvalor.

Então, minha pergunta é: é (i) = 1ilegal neste padrão C?


1
Ainda é um valor l, os parênteses de quebra não mudam isso.
Jeff Mercado

1
Olá pessoal, Por favor, indique qual regra no padrão é legal. Meu compilador segue a regra rigorosamente.
Ravenisadesk #

ientre parênteses não é uma expressão de atribuição. Expressão de atribuição não significa "expressão envolvida em uma atribuição" ou qualquer outra coisa em (i)que se qualifique. Expressões de atribuição são atribuições .
User2357112 suporta Monica

@ user2357112 ié uma expressão de atribuição, a árvore AST é EXPRESSION-> ASSIGNMENT_EXPRESSION-> CONDITIONAL_EXPRESSION-> LOGICAL_OR_EXPRESSION-> CAST_EXPRESSION-> UNARY_EXPRESSION-> POSTFIX_EXPRESSION-> PRIMARY_EXPRESSION-> IDENTIFIER
2011

@reavenisadesk: Uma assignment-expressiongramática não-terminal não é a mesma coisa que uma expressão de atribuição. Grosso modo, an assignment-expressioné uma expressão de atribuição ou qualquer coisa com maior precedência.
User2357112 suporta Monica

Respostas:


8

Para citar n1570 (o último rascunho do padrão C11 antes da publicação):

6.5.1 Expressões primárias (ênfase minha)

5 Uma expressão entre parênteses é uma expressão primária. Seu tipo e valor são idênticos aos da expressão não parênteses . É um valor l, um designador de função ou uma expressão nula se a expressão não-parênteses for, respectivamente, um valor l, um designador de função ou uma expressão nula.

ié um valor l, de acordo com o exposto acima (i). E para responder sua pergunta, a expressão (i) = 1é C. válida


Eu tenho problemas, vamos ver o BNF da expressão primária entre parênteses:, ( expression )portanto, o tipo e o valor são idênticos a expression, e expressioné um assignment expression, e assignment expressioné um primary expression, simplesmente, iserá tratado como assignment expressionfinalmente, portanto, deve seguir a regra de assignment expressionat por último, então deve ser um valor, eu acho.
Ravenisadesk # 12/19

1
@reavenisadesk - Exceto claramente, preto no branco, não é um valor. Ou você i = 1está dizendo que também é inválido?
StoryTeller - Unslander Monica

Eu acho que i = 1é válido por causa disso: assignment-expression: unary-expression assignment-operator assignment-expressionno caso i = 1, eu sou tratado como unary-expression, que é um valor l, não assignment expression, acho que seu i = 1exemplo não é o caso.
Ravenisadesk # 12/19

2
@reavenisadesk: A gramática não diz o que são lvalues ​​ou rvalues. A semântica faz. Para uma expressão de atribuição, C 6.5.16 3 (logo abaixo do título "Semântica") diz uma expressão de atribuição (que é uma frase que descreve a expressão formada com um operador de atribuição, não uma expressão de atribuição , que é um símbolo na gramática ) não é um valor l. Ele não diz que o token da gramática de expressão de atribuição não é um valor l.
Eric Postpischil

1
@reavenisadesk - Eric explicou isso de maneira muito mais eloquente do que eu. Além disso, parece-me que você está escolhendo (i)injustamente aqui. O mesmo ponto sobre semântica se aplica a todo tipo de expressão.
StoryTeller - Unslander Monica

0

O StoryTeller já explicou em que parte do padrão, por que, no seu exemplo, a expressão (i)ainda é um valor mínimo, mas acredito que você está sendo suspenso pelas especificações sem nenhum motivo, por isso, permita-me tentar abordar suas preocupações.

Eu verifiquei o código e as regras e descobri o seguinte: na atribuição semântica da expressão:

Um operador de atribuição deve ter um valor modificável como seu operando esquerdo.

Uma expressão de atribuição possui o valor do operando esquerdo após a atribuição, mas não é um valor l.

A citação inteira refere-se à expressão de atribuição como um todo, não a lhs ou rhs.

"Um operador de atribuição deve ter um valor modificável como seu operando esquerdo." afirma que o lhs deve ser um valor modificável.

"Uma expressão de atribuição tem o valor do operando esquerdo após a atribuição, mas não é um valor l." declara que toda a expressão de atribuição em si tem o valor de lhs e é um rvalue.

Portanto, o seguinte é verdadeiro:

int i;
  i <- modifiable lvalue

(i) = 1;
  (i) <- modifiable lvalue (per StoryTeller's answer)
  1 <- rvalue
  ((i) = 1) <- rvalue

Por que isso é significativo? Considere o seguinte:

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

No meu caso, existem duas expressões de atribuição: (i) = 1e ientre parênteses. Portanto, (i)deve ser um rvalor.

Não, isso está incorreto. (i) = 1é a única expressão de atribuição. Existem duas subexpressões (um identificador entre parênteses (i)e uma constante numérica 1).


0

Esta resposta é inspirada em @Eric Postpischil.

a produção de a assignment-expressioné:

<assignment-expression> ::= <conditional-expression>
                          | <unary-expression> <assignment-operator> <assignment-expression>

no padrão, o assignment expressionespecífico significa expressões com operadores de atribuição. Assim:

<conditional-expression> is not an assignment expression
<unary-expression> <assignment-operator> <assignment-expression> is an assignment expresssion

então a regra:

Uma expressão de atribuição possui o valor do operando esquerdo após a atribuição, mas não é um valor l.

serve apenas para produção <unary-expression> <assignment-operator> <assignment-expression>, não para<conditional-expression>

no exemplo (i) =1, ié um, <assignment-expression>mas não um assignment expression, é um, <conditional-expression>portanto, é um lvaule, portanto, (i)é um lvalue.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.