Привет всем, в следующем коде, что должно быть результатом d после второго выражения?
int d = 1;
d += d++;
Предполагалось, что d будет 3 после, но унарный приращение d ++, похоже, не вступит в силу, и d сохранит значение 2.
Есть ли название для этой ошибки? Он существует для других компиляторов, поддерживающих унарное приращение, например С#?
Если вы посмотрите на сгенерированный ИЛ, вы увидите, почему результат равен 2, а не 3.
IL_0000: ldc.i4.1 // load constant 1 on evaluation stack
IL_0001: stloc.0 // pop and store value in local 0
IL_0002: ldloc.0 // load value of local 0 on evaluation stack
IL_0003: ldloc.0 // repeat, stack is now 1, 1
IL_0004: dup // duplicate topmost value on evaluation stack,
// i.e. stack is now 1, 1, 1
IL_0005: ldc.i4.1 // load constant 1 on evaluation stack
IL_0006: add // add two topmost values on stack,
// i.e. 1 and 1 and push result on stack
IL_0007: stloc.0 // pop and store this value in local 0
IL_0008: add // add the two remaining values on the stack
// which again happens to be 1 and 1 and push result to stack
IL_0009: stloc.0 // pop and store this value in local 0
Иными словами: Запомненное окончательное значение представляет собой сумму 1 и 1.
(приведенный выше код из сборки режима выпуска)
Это не ошибка, она действует точно так, как ожидалось.
Оператор + = распространяется на это:
d = d + d++;
Это означает, что изменение, которое вызывает оператор ++, перезаписывается, когда результат присваивается переменной.
Если вы переписываете свой код таким образом, он установит d, чтобы иметь значение 3:
int d = 1;
d += ++d;
Посмотрите на документацию ++ Operator для объяснения причин, почему ваш пример ведет себя так, как это делается.
Выдержки:
Вторая форма - это постфиксное приращение операция. Результат операции - значение операнда перед ним был увеличен.
Как отметил @Guffa, это не ошибка, просто, что результат вашей операции приращения postfix в d
перезаписывается операцией +=
.
У меня часто возникают вопросы о том, что операторы ++ "сломаны"; почти всегда это происходит потому, что человек, задающий вопрос, используется так, как он работает на каком-то языке, где поведение ++ не определено, например С++. Вот недавняя статья, которую я написал о таком сценарии:
http://blogs.msdn.com/ericlippert/archive/2009/08/10/precedence-vs-order-redux.aspx
Я думаю, что поведение d++
отличается от ++d
, хотя конечный результат, сохраненный в d
, тот же.
Вы пробовали ++ d? Не оценивается ли d ++ после?
... и это будет примером того, почему я считаю, что операторы post/pre-increment/decment очень нечитабельны при использовании в выражении с другими операторами. Поведение, которое вы описываете, является правильным, но трудно рассуждать, что приводит к недоразумениям и ошибкам.
Несмотря на то, что это словосочетание, я бы переписал это как:
int d = 1;
d += d;
++d;
Обратите внимание на использование оператора pre-increment вместо post-increment, чтобы компилятор не думал, что ему нужно сохранить копию старого значения.
Глупый код непредсказуем. Могу я рекомендовать
d += 2;
d ++ и ++ d разные. Также известен как "" Выбрать не разбит "."