precedence - operator logic java




O que é x depois de “x=x++”? (12)

O que acontece (atrás das cortinas) quando isso é executado?

int x = 7;
x = x++;

Ou seja, quando uma variável é pós-incrementada e atribuída a ela mesma em uma instrução? Eu compilei e executei isso. x ainda é 7 mesmo depois de toda a declaração . No meu livro, diz que x é incrementado!


É incrementado após " x = x++; ". Seria 8 se você fizesse " x = ++x; ".


A declaração:

x = x++;

é equivalente a:

tmp = x;   // ... this is capturing the value of "x++"
x = x + 1; // ... this is the effect of the increment operation in "x++" which
           //     happens after the value is captured.
x = tmp;   // ... this is the effect of assignment operation which is
           //     (unfortunately) clobbering the incremented value.

Em suma, a declaração não tem efeito.

Os pontos-chave:

  • O valor de uma expressão de incremento / decremento Postfix é o valor do operando antes do incremento / decremento ocorrer. (No caso de um formulário de prefixo, o valor é o valor do operando após a operação)

  • o RHS de uma expressão de atribuição é completamente avaliado (incluindo quaisquer incrementos, decrementos e / ou outros efeitos colaterais) antes que o valor seja atribuído ao LHS.

Observe que, diferentemente de C e C ++, a ordem de avaliação de uma expressão em Java é totalmente especificada e não há espaço para variação específica da plataforma. Os compiladores só podem reordenar as operações se isso não alterar o resultado da execução do código na perspectiva do encadeamento atual. Nesse caso, um compilador teria permissão para otimizar toda a declaração porque pode ser provado que ela é um não operacional.

Caso ainda não seja óbvio:

  • "x = x ++;" é quase certamente um erro em qualquer programa.
  • O OP (para a pergunta original!) Provavelmente significa "x ++;" em vez de "x = x ++;".
  • Instruções que combinam inc / decrementação automática e atribuição na mesma variável são difíceis de entender e, portanto, devem ser evitadas independentemente de sua correção . Simplesmente não há necessidade de escrever código assim.

Espero que os verificadores de código como FindBugs e PMD sinalizem códigos como este como suspeitos.


Eu acho que essa controvérsia pode ser resolvida sem entrar no código e apenas pensar.

Considere o i ++ & ++ i como funções, digamos Func1 & Func2.

Agora i = 7;
Func1 (i ++) retorna 7, Func2 (++ i) retorna 8 (todo mundo sabe disso). Internamente, ambas as funções incrementam i para 8, mas retornam valores diferentes.

Então eu = i + + chama a função Func1. Dentro da função i incrementa para 8, mas na conclusão a função retorna 7.

Então, finalmente, 7 é alocado para i. (Então, no final, eu = 7)


Isso porque você usou um operador de pós-incremento. Nesta linha de código a seguir

x = x++;

O que acontece é que você está atribuindo o valor de x para x. x ++ incrementa x após o valor de x ser atribuído a x. É assim que os operadores pós-incremento funcionam. Eles trabalham depois que uma declaração foi executada. Então, no seu código, x é retornado primeiro depois, depois é incrementado.

Se você fez

x = ++x;

A resposta seria 8 porque você usou o operador de pré-incremento. Isso incrementa o valor primeiro antes de retornar o valor de x.


O operador Post Increment funciona da seguinte maneira:

  1. Armazene o valor anterior do operando.
  2. Incrementar o valor do operando.
  3. Retorna o valor anterior do operando.

Então a afirmação

int x = 7;
x = x++; 

seria avaliado da seguinte forma:

  1. x é inicializado com o valor 7
  2. operador de pós incremento armazena o valor anterior de x ie 7 para retornar.
  3. Incrementa o x, então agora x é 8
  4. Retorna o valor anterior de x ie 7 e é atribuído de volta a x, então x novamente se torna 7

Então, x é de fato aumentado, mas como x ++ está atribuindo o resultado de volta a x, então o valor de x é substituído por seu valor anterior.


O que acontece quando int x = 7; x = x++; int x = 7; x = x++; ?

ans -> x++ significa primeiro valor de uso de x para expressão e, em seguida, aumentá-lo por 1.
Isto é o que acontece no seu caso. O valor de x em RHS é copiado para variável x em LHS e, em seguida, o valor de x é aumentado em 1.

Similarmente ++x significa -> aumenta o valor de x primeiro por um e depois usa em expressão.
Então, no seu caso, se você fizer x = ++x ; // where x = 7 x = ++x ; // where x = 7
você terá valor de 8.

Para mais clareza, tente descobrir quantas instruções printf irão executar o seguinte código

while(i++ <5)   
  printf("%d" , ++i);   // This might clear your concept upto  great extend

Uma construção como x = x++; indica que você provavelmente está entendendo mal o que o operador ++ faz:

// original code
int x = 7;
x = x++;

Vamos reescrever isso para fazer a mesma coisa, com base na remoção do operador ++ :

// behaves the same as the original code
int x = 7;
int tmp = x; // value of tmp here is 7
x = x + 1; // x temporarily equals 8 (this is the evaluation of ++)
x = tmp; // oops! we overwrote y with 7

Agora, vamos reescrevê-lo para fazer (o que eu acho) que você queria:

// original code
int x = 7;
x++;

A sutileza aqui é que o operador ++ modifica a variável x , ao contrário de uma expressão como x + x , que avaliaria um valor int, mas deixaria a variável x si inalterada. Considere um constructo como o venerável for loop:

for(int i = 0; i < 10; i++)
{
    System.out.println(i);
}

Observe o i++ lá? É o mesmo operador. Nós poderíamos reescrever isso for loop como este e se comportaria da mesma forma:

for(int i = 0; i < 10; i = i + 1)
{
    System.out.println(i);
}

Eu também recomendo não usar o operador ++ em expressões maiores na maioria dos casos. Devido à sutileza de quando modifica a variável original em pré versus pós-incremento ( ++x x++ , respectivamente), é muito fácil introduzir bugs sutis que são difíceis de rastrear.


porque x ++ incrementa o valor AFTER atribuindo-o à variável. assim por diante e durante a execução desta linha:

x++;

o varialbe x ainda terá o valor original (7), mas usando x novamente em outra linha, como

System.out.println(x + "");

vai te dar 8.

Se você quiser usar um valor incrementado de x em sua instrução de atribuição, use

++x;

Isso irá incrementar x por 1, então atribuir esse valor para a variável x.

[Edit] em vez de x = x ++, é apenas x ++; o primeiro atribui o valor original de x a si mesmo, então, na verdade, ele não faz nada nessa linha.


De acordo com o código Byte obtido dos arquivos de classe,

Ambas as atribuições incrementam x, mas a diferença é o tempo de when the value is pushed onto the stack

No Case1 , Push ocorre (e depois atribuído) antes do incremento (essencialmente o seu incremento não faz nada)

No caso 2, o incremento ocorre primeiro (tornando-se 8) e, em seguida, empurrado para a pilha (e, em seguida, atribuído a x)

Caso 1:

int x=7;
x=x++;

Código Byte:

0  bipush 7     //Push 7 onto  stack
2  istore_1 [x] //Pop  7 and store in x
3  iload_1  [x] //Push 7 onto stack
4  iinc 1 1 [x] //Increment x by 1 (x=8)
7  istore_1 [x] //Pop 7 and store in x
8  return       //x now has 7

Caso 2:

int x=7; 
x=++x;

Código Byte

0  bipush 7     //Push 7 onto stack
2  istore_1 [x] //Pop 7 and store in x
3  iinc 1 1 [x] //Increment x by 1 (x=8)
6  iload_1  [x] //Push x onto stack
7  istore_1 [x] //Pop 8 and store in x
8  return       //x now has 8
  • Pilha aqui refere-se a Operand Stack, local: x index: 1 type: int

++x é pré-incremento -> x é incrementado antes de ser usado
x++ é pós-incremento -> x é incrementado após ser usado

int x = 7; -> x get 7 value <br>
x = x++; -> x get x value AND only then x is incremented


x = x++;

é equivalente a

int tmp = x;
x++;
x = tmp;




post-increment