Вопрос о поведении компилятора C #? - PullRequest
2 голосов
/ 12 октября 2009

Привет всем, в следующем коде, каким должен быть результат d после второго выражения?

        int d = 1;
        d += d++;

Можно было бы предположить, что d равно 3, но унарный приращение d ++, похоже, не вступает в силу, и d сохраняет значение 2.

Есть ли название для этой ошибки? Существует ли он для других компиляторов, которые поддерживают унарное приращение, например C #?

Ответы [ 9 ]

34 голосов
/ 12 октября 2009

Это не ошибка, она работает точно так же, как и ожидалось.

Оператор + = распространяется на это:

d = d + d++;

Это означает, что изменение, вызываемое оператором ++, перезаписывается, когда результат присваивается переменной.

16 голосов
/ 12 октября 2009

Если вы посмотрите на сгенерированный IL, вы поймете, почему результат равен 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.

(код выше взят из режима релиза сборки)

12 голосов
/ 12 октября 2009

Если вы переписываете свой код таким образом, он установит для d значение 3:

int d = 1;
d += ++d;

Ознакомьтесь с документацией ++ Operator , чтобы узнать, почему ваш пример ведет себя так, как он.
Выдержки:

Вторая форма - это постфиксный инкремент операция. Результат операции это значение операнда перед ним был увеличен.

Как указал @Guffa, это не ошибка, просто результат операции увеличения постфикса в d перезаписывается операцией +=.

4 голосов
/ 12 октября 2009

Я часто получаю вопросы о том, что операторы ++ "сломаны"; почти всегда это происходит потому, что человек, задающий вопрос, привык к тому, как он работает в каком-то языке, где поведение ++ не определено, как в C ++. Вот недавняя статья, которую я написал о таком сценарии:

http://blogs.msdn.com/ericlippert/archive/2009/08/10/precedence-vs-order-redux.aspx

2 голосов
/ 12 октября 2009

Я думаю, что поведение d++ отличается от ++d, хотя конечный результат, сохраненный в d, тот же.

2 голосов
/ 12 октября 2009

Вы пробовали ++ d? Разве d ++ не оценивается после?

1 голос
/ 12 октября 2009

... и это было бы примером причины, по которой я нахожу, что операторы post / pre-increment /mentment не читаются при использовании в выражении с другими операторами. Поведение, которое вы описываете, является правильным, но его трудно рассуждать, что приводит к недоразумениям и ошибкам.

Несмотря на то, что это более многословно, я бы переписал это как:

int d = 1;
d += d;
++d;

Обратите внимание на использование оператора предварительного увеличения вместо постинкремента, чтобы компилятор не считал необходимым сохранять копию старого значения.

1 голос
/ 12 октября 2009

d ++ и ++ d отличаются. Также известен как " Выбор не сломан. "

1 голос
/ 12 октября 2009

Глупый код непредсказуем. Могу ли я рекомендовать

d += 2;
...