2009-10-12 2 views
2

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

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

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

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

+19

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

+0

Не уверен, что это ошибка, я бы подумал, что ответ будет равен 3, но значение d's, если оценивается в postfix ++, равно 1, поэтому ответ равен 2, или оператор вычисляется на? – kenny

+0

это не ошибка, это особенность :) – idursun

ответ

16

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

(приведенный выше код из режима сборки выпуска)

+0

+1 за попытку проанализировать его на уровне ИЛ. :) – Noldorin

12

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

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

Взгляните на ++ Operator документацию для объяснения того, почему ваш пример ведет себя так, как это делает ,
Выдержка:

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

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

+5

Я думаю, что в вашем пончике есть дыра. Разный вопрос? – kenny

+0

если кто-то переписал * свой код, чтобы посмотреть, как это сделать, я бы немедленно выстрелил из команды. 2 удара и все. – Cheeso

2

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

+0

Будьте осторожны. Оценивается после * чего *, точно? Основное различие между ++ d и d ++ заключается в том, что оценка результата выражения происходит либо до, либо после * хранения * приращенного результата в переменную. Общей ошибкой является то, что оценка постфиксного выражения * как целого * как-то происходит «позже», чем другие части выражения, в которые оно встроено, но это миф. –

+0

Справа. Если ++ было применено после оценки всего выражения, то мы ожидаем увидеть 3. – wsorenson

34

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

Оператор + = расширяется в этом:

d = d + d++; 

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

+6

полное расширение будет: temp = d + d; d = d + 1; d = темп; – QueueHammer

+0

Я думаю, что его проблема связана с d ++, а не с + =. –

2

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

1

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

d += 2; 
+3

Это совсем не непредсказуемо. Спецификация языка очень понятна в отношении того, что должен делать этот код. Я согласен, что это глупо. –

+1

не «непредсказуемо», но определенно «бесполезно трудно предсказать», что, я думаю, достаточно близко. :) – jalf

1

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

Несмотря на то, что это wordier я бы переписать это так:

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

Примечания использования Преинкремента оператора вместо постинкремента, так что компилятор не считает, что нужно сохранить копию от старого значения.

4

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

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