Страницы

Поиск по вопросам

четверг, 28 ноября 2019 г.

Непонятный результат вычисления

#c_sharp


Почему в данном случае a будет равно 20, а не 21?

int a = 10;
a += a++;
Console.WriteLine(a);

    


Ответы

Ответ 1



Это вариация классической задачи про ++i + ++i в несколько упрощенном варианте. В C++ - это undefined behavior, и результатом в большинстве компиляторов будет 21. Цитируя lurkmore: согласно стандартам С и С++, побочные эффекты (то есть инкремент в данном случае) могут быть применены в любой удобный для компилятора момент между двумя точками следования. Конструкцию i = ++i + ++i; компилятор вправе понять и как tmp=i; tmp++; i = tmp; tmp++; i += tmp; и как tmp=i; tmp++; tmp++; i = tmp + tmp; Из-за непредсказуемости поведения этот пример раньше часто предлагали объяснить на собеседованиях :) В C# результатом будет 20, т.к. порядок вычисления явно задан спецификацией. В C# нет никаких точек следования, компилятор не настолько свободен при оптимизации выражений, так что он вычисляет в том порядке, в котором ему приказали: += - это compound assignment operator. Он не самостоятельный оператор (не допускает отдельной перегрузки, и т.д.), а просто шорткат для a = a + a++; Т.е. он просто берет результат вычисления a (10), прибавляет к нему результат вычисления a++ (10) и складывает сумму (20) обратно в a. При этом операнды вычисляются именно слева направо. Процесс вычисления постфиксного оператора a++ описан в спецификации C#, 7.6.9 Postfix increment and decrement operators, и он следующий: Сохраняется текущее значение a. (10) Вызывается оператор (++) с передачей сохраненного значения a в качестве аргумента. Результат вычисления оператора (11) сохраняется в a. (которое позже перезатрется результатом сложения) Сохраненное значение a возвращается как результат операции. (10) Поэтому a + (a++) -> 20 (a++) + a -> 21

Ответ 2



Значение присвоения оператора инкремента не используется ни в одном из путей выполнения, что-то похожее скажет ReSharper на такой код a += a++; сообщение: Value assigned is not used in any execution path Вы попросту потеряете свой постфиксный инкремент, так как он выполняется после того, как выполнится операция сложения и перед присваиванием. Вот если Вы используете префиксный инкремент, тогда получите в результате 21. int a = 10; a += ++a; Console.WriteLine(a); Так как операция префиксного инкремента выполнится раньше, чем выполнится сложение и присваивание. В префиксной форме инкремент или декремент выполняется до использования значения при вычислении выражения. В постфиксной форме инкремент или декремент выполняется после использования значения при вычислении выражения. Ссылки: Оператор ++ (справочник по C#) Оператор -- (Справочник по C#)

Ответ 3



a += a++; ^---------- 10 ^----- 10 ^^--- 11 ^^^--- значение 10, но a=11 ^^------- 10+10 = 20

Комментариев нет:

Отправить комментарий