Depois de pesquisar, li que o operador de incremento requer que o operando tenha um objeto de dados modificável: https://en.wikipedia.org/wiki/Increment_and_decrement_operators .
A partir disso, acho que dá erro de compilação porque (a+b)
é um inteiro temporário e, portanto, não é modificável.
Este entendimento está correto? Esta foi a primeira vez que tentei pesquisar um problema, então se havia algo que eu deveria ter procurado, por favor, avise.
c = a + b + 1
torna sua intenção mais clara e também é mais fácil de digitar. Os operadores de incremento / decremento fazem duas coisas 1. eles e seus argumentos formam uma expressão (que pode ser usada, por exemplo, em um loop for), 2. eles modificam o argumento. Em seu exemplo, você está usando a propriedade 1. mas não a propriedade 2., uma vez que você descarta o argumento modificado. Se você não precisa da propriedade 2. e apenas deseja a expressão, pode simplesmente escrever uma expressão, por exemplo, x + 1 em vez de x ++.Respostas:
É apenas uma regra, só isso, e possivelmente existe para (1) tornar mais fácil escrever compiladores C e (2) ninguém convenceu o comitê de padrões C a relaxá-lo.
Falando informalmente, você só pode escrever
++foo
sefoo
aparecer no lado esquerdo de uma expressão de atribuição comofoo = bar
. Já que você não pode escrevera + b = bar
, você também não pode escrever++(a + b)
.Não há nenhuma razão real para
a + b
não produzir um temporário no qual++
possa operar, e o resultado disso é o valor da expressão++(a + b)
.fonte
++
às vezes tivesse o efeito colateral de modificar algo e às vezes simplesmente não o fizesse.O padrão C11 afirma na seção 6.5.3.1
E "valor modificável" é descrito na seção 6.3.2.1 subseção 1
Portanto,
(a+b)
não é um lvalue modificável e, portanto, não é elegível para o operador de incremento de prefixo.fonte
Você está certo. o
++
tenta atribuir o novo valor à variável original. Então++a
pegará o valor dea
, adiciona1
a ele e, em seguida, atribui de volta aa
. Como, como você disse, (a + b) é um valor temporário e não uma variável com endereço de memória atribuído, a atribuição não pode ser realizada.fonte
Acho que você respondeu principalmente à sua própria pergunta. Eu poderia fazer uma pequena mudança em seu fraseado e substituir "variável temporária" por "rvalue", como C. Gibbons mencionou.
Os termos variável, argumento, variável temporária e assim por diante ficarão mais claros conforme você aprende sobre o modelo de memória do C (parece uma boa visão geral: https://www.geeksforgeeks.org/memory-layout-of-c-program/ )
O termo "rvalue" pode parecer opaco quando você está apenas começando, então espero que o seguinte ajude a desenvolver uma intuição sobre ele.
Lvalue / rvalue estão falando sobre os diferentes lados de um sinal de igual (operador de atribuição): lvalue = lado esquerdo (L minúsculo, não um "um") rvalue = lado direito
Aprender um pouco sobre como C usa a memória (e os registros) será útil para ver por que a distinção é importante. Em grandes pinceladas , o compilador cria uma lista de instruções em linguagem de máquina que calculam o resultado de uma expressão (o rvalue) e, em seguida, coloca esse resultado em algum lugar (o lvalue). Imagine um compilador lidando com o seguinte fragmento de código:
No pseudocódigo de montagem, pode ser parecido com este exemplo de brinquedo:
O operador ++ (e sua contraparte) precisa de um "algum lugar" para modificar, essencialmente qualquer coisa que possa funcionar como um lvalue.
Entender o modelo de memória C será útil porque você terá uma ideia melhor em sua cabeça sobre como os argumentos são passados para funções e (eventualmente) como trabalhar com alocação de memória dinâmica, como a função malloc (). Por razões semelhantes, você pode estudar alguma programação em assembly simples em algum ponto para ter uma ideia melhor do que o compilador está fazendo. Além disso, se você estiver usando o gcc , a opção -S "Parar após o estágio de compilação adequada; não montar." pode ser interessante (embora eu recomende tentar em um pequeno fragmento de código).
Apenas como um aparte: a instrução ++ existe desde 1969 (embora tenha começado no predecessor do C, B):
Seguir essa referência da Wikipedia levará você a um artigo interessante de Dennis Ritchie (o "R" em "K&R C") sobre a história da linguagem C, linkado aqui para sua conveniência: http://www.bell-labs.com/ usr / dmr / www / chist.html onde você pode procurar por "++".
fonte
A razão é que o padrão requer que o operando seja um lvalue. A expressão
(a+b)
não é um lvalue, portanto, não é permitido aplicar o operador de incremento.Agora, pode-se dizer "OK, isso é de fato a razão, mas não há realmente nenhuma * real * razão que não seja" , mas infelizmente a redação específica de como o operador trabalha factualmente não exigem que seja o caso.
Obviamente, você não pode escrever
E += 1
seE
não for um lvalue. O que é uma pena, porque poderíamos muito bem ter dito: "incrementos E por um" e pronto. Nesse caso, aplicar o operador a um não-valor seria (em princípio) perfeitamente possível, à custa de tornar o compilador um pouco mais complexo.Agora, a definição poderia ser reformulada trivialmente (acho que não é nem originalmente C, mas uma herança de B), mas fazer isso mudaria fundamentalmente a linguagem para algo que não é mais compatível com suas versões anteriores. Como o benefício possível é pequeno, mas as implicações possíveis são enormes, isso nunca aconteceu e provavelmente nunca vai acontecer.
Se você considerar C ++ além de C (a questão está marcada como C, mas houve uma discussão sobre sobrecargas de operadores), a história se torna ainda mais complicada. Em C, é difícil imaginar que esse seja o caso, mas em C ++ o resultado de
(a+b)
pode muito bem ser algo que você não pode incrementar de forma alguma, ou incrementar pode ter efeitos colaterais consideráveis (não apenas adicionar 1). O compilador deve ser capaz de lidar com isso e diagnosticar casos problemáticos à medida que ocorrem. Em um lvalue, isso ainda é meio trivial para verificar. Não é assim para qualquer tipo de expressão aleatória dentro de um parêntese que você joga na coitada.Esta não é uma razão real pela qual não poderia ser feito, mas com certeza empresta como uma explicação por que as pessoas que implementaram isso não estão exatamente em êxtase em adicionar tal recurso que promete muito pouco benefício para muito poucas pessoas.
fonte
(a + b) avalia para um rvalue, que não pode ser incrementado.
fonte
++ tenta dar o valor à variável original e, como (a + b) é um valor temporário, não pode realizar a operação. E são basicamente regras das convenções de programação C para facilitar a programação. É isso aí.
fonte
Quando a expressão ++ (a + b) é executada, por exemplo:
fonte