Вопрос о поведении компилятора C #?

2

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

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

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

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

  • 19
    Спрашивать, почему или даже если компилятор не прав, часто является неправильным вопросом. Вопрос о том, почему происходит ваш конкретный вопрос, вероятно, правильный вопрос. Сегодняшний компилятор C # прошел небольшое количество тщательного тестирования и обычно заслуживает сомнений.
  • 0
    Не уверен, что это ошибка, я бы подумал, что ответ также будет равен 3, но значение d, если его оценить в postfix ++, равно 1, поэтому ответ равен 2, или оператор оценивается в?
Показать ещё 9 комментариев
Теги:
increment
compiler-construction

9 ответов

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 за усилия по анализу на уровне IL. :)
35

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

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

d = d + d++;

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

  • 6
    полное расширение будет: temp = d + d; д = д + 1; д = темп;
  • 0
    Я думаю, что его проблема связана с d ++, а не с + =.
12

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

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

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

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

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

  • 5
    Я думаю, что есть дыра в вашем пончике. Другой вопрос?
  • 0
    если бы кто - нибудь переписал свой код, чтобы он выглядел так, я бы немедленно уволил их из команды. 2 удара и все.
4

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

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

2

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

2

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

  • 0
    Быть осторожен. Оценивается после чего , точно? Основное различие между ++ d и d ++ состоит в том, что оценка результата выражения происходит либо до, либо после сохранения увеличенного результата в переменной. Распространено заблуждение полагать, что оценка выражения постфикса в целом каким-то образом происходит «позже», чем другие части выражения, в которое оно встроено, но это миф.
  • 0
    Правильно. Если ++ был применен после того, как все выражение было оценено, то мы ожидаем увидеть 3.
1

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

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

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

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

1

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

d += 2;
  • 3
    Это не непредсказуемо. Спецификация языка очень ясно показывает, что должен делать этот код. Я согласен, что это глупо, хотя.
  • 1
    не «непредсказуемым», но определенно «излишне сложно предсказать», что, я думаю, достаточно близко. :)
1

d ++ и ++ d разные. Также известен как "" Выбрать не разбит "."

Ещё вопросы

Сообщество Overcoder
Наверх
Меню