int main ()
{
int a = 5,b = 2;
printf("%d",a+++++b);
return 0;
}
Este código fornece o seguinte erro:
erro: lvalue necessário como operando de incremento
Mas se eu colocar espaços em toda a extensão a++ +
e ++b
, funcionará bem.
int main ()
{
int a = 5,b = 2;
printf("%d",a++ + ++b);
return 0;
}
O que o erro significa no primeiro exemplo?
x+++++y
é analisado comox ++ ++ + y
, o que viola uma restrição dos operadores de incremento, embora a análisex ++ + ++ y
possa produzir uma expressão correta."Respostas:
printf("%d",a+++++b);
é interpretado como de(a++)++ + b
acordo com a Regra Munch Máxima ! .++
(postfix) não avalia como um,lvalue
mas requer que seu operando seja umlvalue
.! 6.4 / 4 diz que o próximo token de pré-processamento é a mais longa sequência de caracteres que poderia constituir um token de pré-processamento "
fonte
Os compiladores são escritos em etapas. O primeiro estágio é chamado de lexer e transforma os personagens em uma estrutura simbólica. Portanto, "++" se torna algo como um
enum SYMBOL_PLUSPLUS
. Posteriormente, o estágio do analisador transforma isso em uma árvore de sintaxe abstrata, mas não pode alterar os símbolos. Você pode afetar o lexer inserindo espaços (que terminam com os símbolos, a menos que estejam entre aspas).Os lexers normais são gananciosos (com algumas exceções), então seu código está sendo interpretado como
A entrada para o analisador é um fluxo de símbolos, então seu código seria algo como:
Que o analisador considera sintaticamente incorreto. (EDITAR com base em comentários: Semanticamente incorreto porque você não pode aplicar ++ a um valor r, no qual um ++ resulta)
é
O que está ok. Assim como seus outros exemplos.
fonte
a++
).a++
resulta em um rvalue.x = 10&987&&654&&321
é ilegal, mas estranhamentex = 10&987&&654&&&321
é legal.O lexer usa o que geralmente é chamado de algoritmo de "mastigação máxima" para criar tokens. Isso significa que, à medida que está lendo os caracteres, ele continua lendo os caracteres até encontrar algo que não pode ser parte do mesmo token que já possui (por exemplo, se estiver lendo dígitos, então o que tem é um número, se encontrar an
A
, ele sabe que não pode ser parte do número. então ele para e deixa oA
no buffer de entrada para usar como o início do próximo token). Em seguida, ele retorna esse token para o analisador.Nesse caso, isso significa que
+++++
é lexed comoa ++ ++ + b
. Como o primeiro pós-incremento produz um rvalue, o segundo não pode ser aplicado a ele e o compilador fornece um erro.Apenas FWIW, em C ++ você pode sobrecarregar
operator++
para gerar um lvalue, o que permite que isso funcione. Por exemplo:Compila e executa (embora não faça nada) com os compiladores C ++ que tenho à mão (VC ++, g ++, Comeau).
fonte
16FA
é um número hexadecimal perfeitamente fino que contém um A.0x
no início ainda o tratará como16
seguido porFA
, não um único número hexadecimal.0x
fazia parte do número.x
um dígito, parecia totalmente desnecessário.Este exemplo exato é coberto no esboço da norma C99 ( mesmos detalhes em C11 ) seção 6.4 Elementos lexicais, parágrafo 4, que diz:
que também é conhecida como regra de mastigação máxima, usada na análise lexical para evitar ambigüidades e funciona pegando o máximo de elementos possível para formar um token válido.
o parágrafo também tem dois exemplos, o segundo é uma correspondência exata para sua pergunta e é o seguinte:
que nos diz que:
será analisado como:
que viola as restrições do incremento posterior, uma vez que o resultado do primeiro incremento posterior é um rvalue e o incremento posterior requer um lvalue. Isso é abordado na seção
6.5.2.4
Operadores de incremento e decremento do Postfix que diz ( ênfase minha ):e
O livro C ++ Gotchas também cobre este caso em
Gotcha #17
Maximal Munch Problems . É o mesmo problema em C ++ e também dá alguns exemplos. Isso explica ao lidar com o seguinte conjunto de caracteres:o analisador léxico pode fazer uma das três coisas:
-
,>
e*
->
e*
->*
A regra da mastigação máxima permite evitar essas ambigüidades. O autor aponta que ( no contexto C ++ ):
O primeiro exemplo seriam modelos cujos argumentos de modelo também são modelos (o que foi resolvido em C ++ 11 ), por exemplo:
Que interpreta os colchetes angulares de fechamento como o operador de deslocamento e, portanto, um espaço é necessário para desambiguar:
O segundo caso envolve argumentos padrão para ponteiros, por exemplo:
seria interpretado como
*=
operador de atribuição, a solução neste caso é nomear os parâmetros na declaração.fonte
>>
regra é solicitada em: stackoverflow.com/questions/15785496/…Seu compilador tenta desesperadamente analisar
a+++++b
e interpretar como(a++)++ +b
. Agora, o resultado do pós-incremento (a++
) não é um lvalue , ou seja, não pode ser pós-incrementado novamente.Nunca escreva esse código em programas de qualidade de produção. Pense no pobre sujeito que está vindo atrás de você e que precisa interpretar seu código.
fonte
a ++ retorna o valor anterior, um rvalue. Você não pode incrementar isso.
fonte
Porque causa comportamento indefinido.Qual é?
Sim, nem você nem o compilador sabem disso.EDITAR:
O verdadeiro motivo é o dito pelos outros:
É interpretado como
(a++)++ + b
.mas o incremento posterior requer um lvalue (que é uma variável com um nome), mas (a ++) retorna um rvalue que não pode ser incrementado, levando à mensagem de erro que você recebe.
Obrigado aos outros por apontar isso.
fonte
a+++b
sempre éa++ + b
a++ ++ +b
que não pode ser analisado.a+++++b
não avaliar a(a++)++)+b
. Certamente com o GCC, se você inserir esses colchetes e reconstruir, a mensagem de erro não mudará.Acho que o compilador vê isso como
c = ((a ++) ++) + b
++
deve ter como operando um valor que pode ser modificado. a é um valor que pode ser modificado.a++
no entanto, é um 'rvalue', não pode ser modificado.Pela forma como o erro que eu ver em GCC C é o mesmo, mas de forma diferente redigida:
lvalue required as increment operand
.fonte
Siga esta ordem de precessão
1. ++ (pré-incremento)
2. + - (adição ou subtração)
3. "x" + "y" adiciona a sequência
int a = 5,b = 2; printf("%d",a++ + ++b); //a is 5 since it is post increment b is 3 pre increment return 0; //it is 5+3=8
fonte