Какая разница между 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.

Ответ 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.

НТН