Какая разница между X = X ++; vs X ++;?
Вы когда-нибудь пробовали это раньше?
static void Main(string[] args)
{
int x = 10;
x = x++;
Console.WriteLine(x);
}
Выход: 10.
но для
static void Main(string[] args)
{
int x = 10;
x++;
Console.WriteLine(x);
}
Выход: 11.
Может ли кто-нибудь объяснить, почему это?
Ответы
Ответ 1
X ++ увеличит значение, но затем вернет его старое значение.
Итак, в этом случае:
static void Main(string[] args)
{
int x = 10;
x = x++;
Console.WriteLine(x);
}
У вас есть X в 11 только на мгновение, затем он возвращается к 10, потому что 10 - это возвращаемое значение (x ++).
Вместо этого вы можете сделать это для одного и того же результата:
static int plusplus(ref int x)
{
int xOld = x;
x++;
return xOld;
}
static void Main(string[] args)
{
int x = 10;
x = plusplus(x);
Console.WriteLine(x);
}
Также стоит упомянуть, что у вас был бы ожидаемый результат 11, если бы вы сделали:
static void Main(string[] args)
{
int x = 10;
x = ++x;
Console.WriteLine(x);
}
Ответ 2
В присваивании x = x++
сначала вы извлекаете старое значение x
для использования при оценке выражения правой части, в данном случае "x"; то вы увеличиваете x
на 1. Наконец, вы назначаете результаты оценки выражения (10) на x
через оператор присваивания.
Возможно, эквивалентный код сделает сообщение затруднительным:
var tmp = x;
x++;
x = tmp;
Это эквивалент вашего кода x = x++
в С#.
Ответ 3
Поведение x ++ - это увеличение x, но возвращающее значение до. По этой причине он называется пошаговым приращением.
Итак, x = x ++; просто введите
1. верните значение, затем
2. increment x, то
3. присвойте исходное значение (возвращенному на шаге 1) x в x.
Ответ 4
x = ++ x
будет равно 11.
Ответ 5
x++;
выполняет следующие действия:
int returnValue = x;
x = x+1;
return returnValue;
Как вы можете видеть, исходное значение сохраняется, x увеличивается, а затем возвращается исходное значение.
То, что это делает, это сохранить значение 10 где-то, установив x равным 11, а затем возвратить 10, что приведет к тому, что x будет восстановлено до 10. Обратите внимание, что x фактически становится 11 для нескольких циклов (при условии, что нет оптимизация компилятора).
Ответ 6
Это не отвечает на вопрос напрямую, но почему в мире кто-нибудь будет использовать
x = x++;
?
Он полностью поражает цель оператора post-increment/pre-increment.
Ответ 7
Вы можете думать об этом так:
int x = 10;
X является контейнером и содержит значение 10.
x = x++;
Это можно разбить на:
1) increment the value contained in x
now x contains 11
2) return the value that was contained in x before it was incremented
that is 10
3) assign that value to x
now, x contains 10
Теперь напечатайте значение, содержащееся в x
Console.WriteLine(x);
И, неудивительно, он печатает 10.
Ответ 8
По определению x ++ возвращает значение x, а затем увеличивает x.
http://blogs.msdn.com/lucabol/archive/2004/08/31/223580.aspx
Ответ 9
Первое, что вы делаете, называется "post-increment", что означает
int x = 10;
x++; //x still is 10
Console.WriteLine(x); //x is now 11(post increment)
так что момент, который вы назначаете x = x ++; x по-прежнему 10, что вы могли бы сделать, если вам нужно x, чтобы быть 11 в этой строке write ++ x (подумайте, что он называется pre increment correct me if im wrong)... альтернативно right x ++; и x = x ++;
вопрос, зависит ли он от строки или оператора, что означает, что она будет увеличиваться после;
Ответ 10
Попробуйте вызвать ++ x и посмотрите, работает ли это.
Ответ 11
Помещение оператора инкремента после переменной означает, что приращение и присваивание происходит после вычисления выражения... так
Исходное выражение
x = x ++;
переводит на
1. Оцените значение x и сохраните значение в памяти тиража
... Теперь выполните код, вызываемый оператором ++.... (шаги 2 и 3)
2. Инкрементное значение x (в переходной памяти)
3. Назначьте добавочное значение в место хранения x... Теперь продолжайте с остальной частью выполнения строки, слева, там знак =...
5. Таким образом, присвойте значение, сохраненное на шаге 1 (неинкрементное значение), в выражение слева от = sign... которое равно x
Ответ 12
Возможно, я не прав, но мне легче понять результат на аналогичном примере:
public static void main(String[] args) {
int x = 10;
int y = 0;
y = x + x++; //1, 2, 3, 4
x += x; //5
System.out.println("x = " + x + "; y = " + y); //6
}
Пошаговое рассмотрение операции y = x + x ++:
- Компьютер берет значение x и добавляет его к значению x (10 + 10 = 20)
- Компьютер НАПРАВЛЯЕТ РЕЗУЛЬТАТ К ВРЕМЕННОЙ ПЕРЕМЕННОЙ (temp = 20)
- Приращения копутера x (10 + 1 = 11)
- Компьютер НАПРАВЛЯЕТ РУССКУЮ ПРАВУЮ СТОРОНУЮ ЭКСПЛУАТАЦИЮ, ЗАПОМНЕННУЮ В temp, к переменной y (20)
- Компьютер принимает значение x и добавляет его к значению x (11 + 11 = 22)
- Конечный результат: x = 22; y = 20
А теперь вернемся к нашему примеру и выполните те же шаги:
public static void main(String[] args) {
int x = 10;
x = x++; //1, 2, 3, 4
System.out.println(x); //5
}
- Компьютер принимает значение x (10)
- Компьютер НАПРАВЛЯЕТ РЕЗУЛЬТАТ ВРЕМЕННОЙ ПЕРЕМЕННОЙ (temp = 10)
- Приращения копутера x (10 + 1 = 11)
- Компьютер НАПРАВЛЯЕТ РУЧКУ ПРАВОВОЙ СТОРОНЫ ОПЕРАЦИИ, ЗАПОМНЕННОЙ В temp, к переменной x (10)
- Конечный результат: x = 10
Ответ 13
Я знаю, что есть много ответов и принято, но я все равно поставлю свои два цента для еще одной точки зрения.
Я знаю, что этот вопрос был С#, но я предполагаю, что для чего-то вроде постфиксного оператора он не имеет другого поведения, чем C:
int main(){
int x = 0;
while (x<1)
x = x++;
}
Сборка (да, я ее отредактировал, чтобы сделать ее более читаемой), сгенерированной компилятором, показывает
...
mov -8(rbp), 0 ; x = 0
L1:
cmp -8(rbp), 1 ; if x >= 1,
jge L2 ; leave the loop
mov eax, -8(rbp) ; t1 = x
mov ecx, eax ; t2 = t1
add ecx, 1 ; t2 = t2 + 1
mov -8(rbp), ecx ; x = t2 (so x = x + 1 !)
mov -8(rbp), eax ; x = t1 (kidding, it the original value again)
jmp L1
L2:
...
Эквивалентно, цикл делает что-то вроде:
t = x
x = x + 1
x = t
Боковое примечание: включение любых оптимизаций дает вам некоторый результат сборки следующим образом:
...
L1:
jmp L1
...
он даже не хочет хранить значение, которое вы ему сказали, чтобы дать x!
Ответ 14
Как автономный оператор, x++;
является как приращением, так и присваиванием. Кажется, что есть некоторые путаницы относительно того, что происходит, когда. Если мы имеем
int x = 10;
int y = (x++) + 2;
Мы получим x = 11
и y = 12
. Текущее значение x назначается, а , затем имеет место увеличение и переназначение x. Итак, при использовании той же переменной
int x = 10; // Create a variable x, and assign an initial value of 10.
x = x++; // First, assign the current value of x to x. (x = x)
// Second, increment x by one. (x++ - first part)
// Third, assign the new value of x to x. (x++ - second part)
Как бы вы ни смотрели на это, новое значение x равно 11.
Я был совершенно не прав на этом.
Ответ 15
Простое объяснение:
x ++ - это постфиксная инкрементация.
Что делает компилятор:
a) Назначьте значение x x
b) Увеличьте временное значение x (я думаю, он может быть даже оптимизирован)
c) Отбросить временное значение x
Если вы хотите, чтобы код возвращал 11 с назначением, напишите:
x = ++ x;
Ответ 16
Результат присваивания
x = x++;
есть undefined в C и С++ , и я бы предпочел то же самое с С#.
Таким образом, фактическая последовательность выполняемых операций зависит от того, как компилятор решает ее реализовать, нет гарантии, произойдет ли сначала назначение или инкремент.
(это хорошо определено в С#, как указал Джон Скит в комментариях. Хотя теперь я чувствую, что этот ответ имеет гораздо меньшую ценность, я сохраняю этот пост неустановленным для вопроса OP и его ответ в комментарии.)
Однако в этом случае появляется последовательность выполняемых операций:
- сохраняется старое значение (10) x.
- x увеличивается для части ++
- старое значение теперь присваивается x для присваивания
Таким образом, хотя приращение происходит, оно набирается заданием со старым значением, таким образом сохраняя x в 10.
НТН