Что такое x после "x = x++"?


что происходит (за занавесками), когда это выполняется?

int x = 7;
x = x++;

то есть, когда переменная пост инкрементируется и присваивается себе в одном операторе? Я скомпилировал и выполнил это. x еще 7 даже после всего заявление. В моей книге говорится, что x увеличивается!

17 255

17 ответов:

x не увеличивается. Но вы присваиваете старое значение x обратно в себя.


x = x++;
  1. x++ С шагом x и возвращает его старое значение.
  2. x = присваивает себе старое значение.

Итак, в конце концов,x возвращается к исходному значению.

x = x++;

эквивалентно

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

инструкции:

x = x++;

эквивалентно:

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.

короче, заявление не имеет никакого эффекта.

ключевые моменты:

  • значение постфиксного выражения инкремента / декремента является значением операнда до происходит приращение/уменьшение. (В случае префиксной формы значение является значением операнда после операции)

  • в RHS выражения присваивания полностью вычисляется (включая любые приращения, декременты и/или другие побочные эффекты) до значение присваивается LHS.

обратите внимание, что в отличие от C и c++, порядок вычисления выражения в Java полностью задан, и нет места для изменения платформы. Компиляторы могут изменять порядок операций только в том случае, если это не изменяет результат выполнения кода из перспектива текущего потока. В этом случае компилятору будет разрешено оптимизировать весь оператор, потому что можно доказать, что это не-op.


в случае, если это еще не очевидно:

  • "x = x++;" почти наверняка является ошибкой в любой программе.
  • ОП (для исходного вопроса!) вероятно, означало " x++;", а не"x = x++;".
  • заявления, сочетающие автоматическое ВКЛ/декремента и назначения ту же переменную трудно понять, и следует избегать независимо от их правильности. Просто нет необходимости писать такой код.

надеюсь, кодовые шашки, такие как FindBugs и PMD, будут помечать такой код как подозрительный.

int x = 7;
x = x++;

Он имеет неопределенное поведение в C а для Java см. ответ. Это зависит от компилятора, что происходит.

конструкции типа x = x++; указывает, что вы, вероятно, неправильно поняли, что ++ оператор:

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

давайте перепишем это, чтобы сделать то же самое, на основе удаления ++ оператор:

// 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

теперь давайте перепишем его, чтобы сделать (то, что я думаю) вы хотели:

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

тонкость здесь в том, что ++ оператор изменяет переменную x, в отличие от выражения типа x + x, что бы оценить значение int, но оставьте переменную x сам без изменений. Рассмотрим такую конструкцию, как почтенный for петли:

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

обратите внимание на i++ там? Это тот же оператор. Мы могли бы переписать это for цикл, как это, и он будет вести себя так же:

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

я также рекомендую не использовать ++ оператор в больших выражениях в большинстве случаев. Из-за тонкости , когда он изменяет исходную переменную в pre-versus пост-инкремент (++x и x++, соответственно), очень легко ввести тонкие ошибки, которые трудно отследить.

согласно коду байта полученных из class-файлов

оба назначения увеличивают x, но разница-это время when the value is pushed onto the stack

на Case1, Push происходит (а затем позже назначается) до инкремента (по сути, это означает, что ваш инкремент ничего не делает)

на Case2, инкремент происходит сначала (что делает его 8), а затем толкнул в стек (а затем присвоен x)

случае 1:

int x=7;
x=x++;

Байт-Код:

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

Пример 2:

int x=7; 
x=++x;

Байт-Код

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
  • стек здесь относится к стеку операндов, локальный: X индекс: 1 тип: int

он увеличивается после "x = x++;". Это было бы 8, если бы вы сделали"x = ++x;".

приращение происходит после вызова x, поэтому x по-прежнему равно 7. ++x будет равно 8, Когда x называется

при повторном назначении значения для x это все еще 7. Попробуй x = ++x и вы получите еще 8

x++; // don't re-assign, just increment
System.out.println(x); // prints 8

потому что x++ увеличивает значение после присвоения его переменной. так и во время выполнения этой строки:

x++;

varialbe x по-прежнему будет иметь исходное значение (7), но снова использует x в другой строке, например

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

даст вам 8.

Если вы хотите использовать увеличенное значение x в операторе присваивания, используйте

++x;

это увеличит x на 1, а затем присвоит это значение переменной x.

[редактирование] вместо x = x++ это просто x++; первый присваивает себе исходное значение x, поэтому он фактически ничего не делает в этой строке.

оператор приращения Post работает следующим образом:

  1. сохранить Предыдущее значение операнда.
  2. увеличить значение операнда.
  3. возвращает Предыдущее значение операнда.

Итак, утверждение

int x = 7;
x = x++; 

будет оцениваться следующим образом:

  1. x инициализируется значением 7
  2. оператор Post increment сохраняет Предыдущее значение x, т. е. 7 для возврата.
  3. увеличивает x, Итак, теперь x - 8
  4. возвращает Предыдущее значение x, т. е. 7, и оно присваивается обратно x, поэтому x снова становится 7

таким образом, x действительно увеличивается, но поскольку x++ присваивает результат обратно x, поэтому значение x переопределяется на его Предыдущее значение.

что происходит, когда int x = 7; x = x++;?

ans ->x++ означает сначала использовать значение x для выражения, а затем увеличить его на 1.
Вот что происходит в вашем случае. Значение x на RHS копируется в переменную x на LHS, а затем значение x увеличивается на 1.

аналогично ++x означает -> сначала увеличьте значение x на единицу, а затем используйте в выражении .
Так что в вашем случае, если вы делаете x = ++x ; // where x = 7
вы получите значение 8.

для большей ясности попробуйте узнать, сколько оператор printf будет выполнять следующий код

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

++x это пре-инкремент -> x увеличивается до используется
x++ - Это пост-инкремент -> x увеличивается после используется

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

это означает: x++ не равно x = x+1

потому что:

int x = 7; x = x++;
x is 7

int x = 7; x = x = x+1;
x is 8

и теперь это кажется немного странным:

int x = 7; x = x+=1;
x is 8

очень зависит от компилятора!

Я думаю, что этот спор можно решить, не вдаваясь в код и просто думая.

рассмотрим i++ & ++i как функции, скажем Func1 & Func2.

теперь i=7;
Func1 (I++) возвращает 7, Func2 (++i) возвращает 8 (все это знают). Внутренне обе функции увеличивают i до 8 , но они возвращают разные значения.

поэтому i = i++ вызывает функцию Func1. Внутри функции I увеличивается до 8, но по завершении функция возвращает 7.

таким образом, в конечном итоге 7 выделяется i. (Так что в конце концов, i = 7)

x = x++;

Это оператор постинкремента. Это следует понимать как"использовать значение операнда, а затем увеличить операнд".

Если вы хотите, чтобы произошло обратное, т. е." увеличить операнд, а затем использовать значение операнда", вы должны использовать оператор предварительного приращения, как показано ниже.

x = ++x;

этот оператор сначала увеличивает значение X на 1, а затем присваивает значение х.

Это потому, что вы использовали оператор post-increment. В следующей строке кода

x = x++;

что происходит, так это то, что вы присваиваете значение x x. x++ инкременты x после того, как значение x присваивается x. Вот как работают операторы после инкремента. Они работают после выполнения инструкции. Таким образом, в вашем коде x возвращается сначала после того, как затем он увеличивается.

Если ты

x = ++x;

ответ будет 8, потому что вы использовали пре-инкремент оператор. Это увеличивает значение сначала перед возвращением значения x.