С# Pre- & Post Increment confusions
Я немного запутался в том, как компилятор С# обрабатывает до и после приращений и декрементов.
Когда я закодирую следующее:
int x = 4;
x = x++ + ++x;
x
будет иметь значение 10 после этого. Я думаю, это связано с тем, что pre-increment устанавливает x
в 5
, что делает его 5+5
равным 10
. Затем пост-инкремент будет обновлять x
до 6
, но это значение не будет использоваться, потому что тогда 10
будет присвоено x
.
Но когда я код:
int x = 4;
x = x-- - --x;
тогда x
будет 2
. Может ли кто-нибудь объяснить, почему это так?
Ответы
Ответ 1
x--
будет 4, но будет 3 в момент --x
, поэтому он будет заканчиваться на 2, тогда у вас будет
x = 4 - 2
btw, ваш первый случай будет x = 4 + 6
Вот небольшой пример, который будет печатать значения для каждой части, возможно, таким образом вы поймете это лучше:
static void Main(string[] args)
{
int x = 4;
Console.WriteLine("x++: {0}", x++); //after this statement x = 5
Console.WriteLine("++x: {0}", ++x);
int y = 4;
Console.WriteLine("y--: {0}", y--); //after this statement y = 3
Console.WriteLine("--y: {0}", --y);
Console.ReadKey();
}
выводится
x++: 4
++x: 6
y--: 4
--y: 2
Ответ 2
Давайте посмотрим на IL, который генерируется из этого утверждения
IL_0002: ldloc.0
Загружает значение x в стек. Stack = > (4)
IL_0003: dup
Дублирует самый верхний элемент в стеке. Stack = > (4, 4)
IL_0004: ldc.i4.1
Нажмите 1 на стек. Stack = > (1, 4, 4)
IL_0005: sub
Вычтите два верхних значения и нажмите результат на стек. Stack = > (3, 4)
IL_0006: stloc.0
Храните верхнее значение стека обратно в x. Stack = > (4)
IL_0007: ldloc.0
Загрузите значение x обратно в стек. Stack = > (3, 4)
IL_0008: ldc.i4.1
Загрузите значение 1 в стек. Stack = > (1, 3, 4)
IL_0009: sub
Вычтите два. Stack = > (2, 4)
IL_000A: dup
Дублируйте верхнее value = > (2, 2, 4)
IL_000B: stloc.0
Сохраните верхнее значение обратно на x. Stack = > (2, 4)
IL_000C: sub
Вычтите два верхних значения. Stack = > (2)
IL_000D: stloc.0
Сохраните это значение обратно в x. x == 2
Ответ 3
Из вашего комментария:
Я подумал, что после/до оценки полной кодовой строки выполняются пост-и предварительные приращения, но они выполняются после/перед оценкой каждого элемента в выражении.
Ваше недоразумение является чрезвычайно распространенным. Обратите внимание, что на некоторых языках, таких как C, он не указывается, когда побочный эффект становится видимым, и поэтому он является законным, но не обязательным, чтобы ваше утверждение было истинным в C.
Это не относится к С#; в С# побочные эффекты кода в левой части выражения всегда наблюдаются до того, как код с правой стороны выполняет (из одного потока, в многопоточных сценариях все ставки отключены.)
Для более подробного объяснения того, что делают операторы приращения в С#, см. ниже:
В чем разница между я ++ и ++ i?
Есть много ссылок на статьи, которые я написал на этой часто недопонимаемой теме.
Ответ 4
Самое интересное, что вы получите совершенно другой ответ с С++. Чистый компилятор.
int x = 4;
x = x++ + ++x; // x = 11
x = 4;
x = x-- - --x; // x = -1
Конечно, разница в результатах определяется другой семантикой - она кажется нормальной. Но, несмотря на понимание того факта, что два компилятора .net не ведут себя аналогичным образом, такие основные вещи меня тоже путают.
Ответ 5
В этом примере
int x = 4;
x = x++ + ++x;
вы можете сломать его так:
x = 4++; which is = 5
x = 4 + ++5; which is 4 + 6
x = 10
Аналогично,
int x = 4;
x = x-- - --x;
Здесь
x = 4--; which is = 3
x = 4 - --3; which is 4 - 2
x = 2
Проще говоря, вы можете сказать, замените текущее значение x, но для каждого ++ или - добавьте/вычтите значение из x.
Ответ 6
Я думаю, что объяснение для случая ++ + ++ неверно:
команда........... значение x
.................. неопределенными
int x = 4.......... 4
x ++............... 5 (первое слагаемое равно 4)
++ x............... 6 (второе слагаемое равно 6)
x = summand1 + summand2..4 + 6 = 10
Аналогичным объяснением для - - - случая является
команда........... значение x
.................. неопределенными
int x = 4.......... 4
x --............... 3 (subtactor is 4)
- x............... 2 (subtrahend is 2)
x = subtractor-subtrahend..4-2 = 10