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

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

int x = 7;
x = x++;

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

18 ответов

Решение

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.

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

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

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

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

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


Если это еще не очевидно:

  • "х = х ++;" почти наверняка ошибка в любой программе.
  • ОП (для первоначального вопроса!), Вероятно, означало "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);
}

Я также рекомендую против использования ++ оператор в больших выражениях в большинстве случаев. Из-за тонкости того, когда она изменяет исходную переменную в сравнении с постинкрементным (++x а также 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 index: 1 type: int

Постинкрементный оператор работает следующим образом:

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

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

int x = 7;
x = x++; 

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

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

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

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

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

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

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

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

x++;

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

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

даст вам 8.

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

++x;

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

[Edit] вместо 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++ это постинкремент -> х увеличивается после использования

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

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

Самое простое объяснение!

Это связано с тем, что ++ после того, как операнд выполняет пост-инкремент, означает, что сначала значение было присвоено переменной, а затем увеличено. Хотя, если вы ожидаете, что значение x будет 8, вам следует предварительно увеличить его, как указано ниже:

Х = х ++;

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

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

х = ++ х;

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

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

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

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

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

Таким образом, в конечном итоге 7 получает я. (Итак, в итоге я = 7)

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

x = x++;

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

Если вы сделали

x = ++x;

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

Другие вопросы по тегам