I = я ++ не увеличивает i. Зачем?
Возможные дубликаты:
Почему это происходит в бесконечном цикле?
Такие вещи, как i = i++
, имеют поведение undefined в C и С++, потому что значение скалярного объекта изменяется дважды внутри одного и того же выражения без промежуточной точки последовательности.
Однако я полагаю, что эти выражения имеют хорошо определенное поведение на С# или Java, потому что AFAIK оценивает аргумент слева направо и есть точки последовательности по всему.
Тем не менее, я ожидаю, что i = i++
будет эквивалентен i++
. Но это не так. Следующая программа выводит 0
.
using System;
class Program
{
static void Main(string[] args)
{
int i = 0;
i = i++;
Console.WriteLine(i);
}
}
Не могли бы вы помочь мне понять, почему?
Отказ от ответственности:
Я полностью осознаю, что независимо от того, определено ли поведение вышеупомянутых конструкций, они глупы, бесполезны, нечитаемы, не нужны и не должны использоваться в коде. Мне просто интересно.
Ответы
Ответ 1
Поведение хорошо определено в С#, а порядок оценки:
- Левая сторона
i
оценивается переменной i
- Правая сторона оценивается как 0, а
i
увеличивается (теперь i==1
)
- Выполнение назначения выполняется, оно устанавливает
i
в 0. (теперь i==0
)
Конечный результат i==0
.
В общем вы сначала создаете дерево выражений. Чтобы оценить его, вы сначала оцениваете левую сторону, затем правую сторону и, наконец, операцию в корне. Сделайте это рекурсивно.
Ответ 2
Результатом выражения post-increment i++
является исходное значение i
. Поэтому после того, как i++
был оценен (с увеличением i
), вы назначаете старое значение i
... i
.
Просто используйте
i++;
;)
Ответ 3
i = ++i
- это код, который делает то, что, по вашему мнению, происходит здесь. i++
действительно ведет себя по-другому.
С i++
значение i
увеличивается, но значение i++
не является новым значением i
, это предыдущее значение. Поэтому, когда вы делаете i = i++
, вы говорите: "Увеличьте значение i
, затем установите i
в старое значение".
Ответ 4
Ну, выражение правой стороны должно быть оценено до назначения. Теперь i++
будет оценивать текущее значение i
, а значение я впоследствии увеличится на единицу. Тем не менее, назначение еще не выполнено, и когда оно будет, оно будет перезаписывать текущее значение i
(1) с любым выражением rhs, которое было в вашем случае равным 0.
Ключевое различие между ++i
(pre-increment, которое оценивается с новым значением i
после) и i++
или пост-приращением, которое оценивается текущее значение i
до.
Если бы вы использовали ++i
вместо этого, выражение в правой части было бы оценено до 1, в результате чего я == 1.