Что такое х после "х = х ++"?
Что происходит (за занавесом), когда это выполняется?
int x = 7;
x = x++;
То есть, когда переменная увеличивается на единицу и присваивается себе в одном выражении? Я скомпилировал и выполнил это. x
еще 7 даже после всего заявления. В моей книге говорится, что x
увеличивается!
18 ответов
x
действительно увеличивается. Но вы присваиваете старое значение x
обратно в себя.
x = x++;
x++
приращенийx
и возвращает свое старое значение.x =
присваивает старое значение себе
Итак, в конце концов, x
получает обратно к своему начальному значению.
Заявление:
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
Постинкрементный оператор работает следующим образом:
- Сохранить предыдущее значение операнда.
- Увеличьте значение операнда.
- Вернуть предыдущее значение операнда.
Итак, утверждение
int x = 7;
x = x++;
будет оцениваться следующим образом:
- х инициализируется значением 7
- постинкрементный оператор сохраняет предыдущее значение x, т. е. 7 для возврата.
- Увеличивает х, так что теперь х равен 8
- Возвращает предыдущее значение 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.