@VL5438

Порядок выполнения действий в выражении --i + i++?

Если написать вот такой код в JavaScript:
let i = 1;
console.log( --i + i++ ); // 0

Результат будет 0. Почему?
Если посмотреть на таблицу приоритетов операторов, то видно что самым высоким приоритетом тут обладает постфиксный инкремент (i++) и в соответствии с этим должен выполнится первым, далее префиксный декремент (--i) и сложение. В результате чего мы должны получить не 0, а 2 в качестве результата.
По ссылке выше так же описана ассоциативность, которая как там описано определяет порядок выполнения операторов с одинаковым приоритетом, но у нас все операторы имеют разный приоритет.

Если код выше написать на C++:
int i = 1;
cout << --i + i++; // 1

То в качестве результата мы получим 1 (для C++ использовался онлайн компилятор: ссылка).

Так же можно попробовать заменить постфиксный инкремент на вызов (какой-либо) функции - вызов функции так же будет выполняться после префиксного декремента (хотя функция имеет приоритет более высокий):
"use strict"
function f(x) {
  console.log(x); // Результат: 0. А значит вызов функции произошел после декремента
  return x;
}
let i = 1;
console.log( --i + f(i) ); // Результат: 0.


UPD: Этим вопросом я хочу узнать от чего зависит порядок вычисления выражений, ведь по данным примерам видно, что операторы имеющие приоритет более высокий необязательно вычисляются раньше (это особенно видно из последнего примера с функцией).
  • Вопрос задан
  • 739 просмотров
Решения вопроса 2
Aetae
@Aetae Куратор тега JavaScript
Тлен
--i + i++ - это не атомарное выражение. Это (--i) + (i++) - как раз потому что приоритеты инкремента выше приоритетов сложения. Javascript не вычисляет ничего разом, он вычисляет всё пошагово слева направо. Приоритетность разбивается на токены не снизу вверх, а сверху-вниз. Если два подвыражения с более высоким приоритетом оказались после разбивки слева и справа, то левый выполняется первым, правый вторым, т.к. для выражения с низким приоритетом не важно насколько приоритет подвыражений выше - для него они равноправны.
Никакого UB в отличие от С тут быть не может.
Ответ написан
@Mercury13
Программист на «си с крестами» и не только
В математике на бумаге можно вычислять в любом порядке, потому и говорят на уроках: «что в скобках, то и первым».

В компьютерах есть побочные эффекты и желание сделать поменьше промежуточной памяти, потому приоритет и ассоциативность служат только для расстановки неявных скобок — а порядок вычисления прост: «сначала левая часть, потом правая» (для некоторых операций наоборот).

В Си даже это «левая → правая» зачастую остаётся за реализацией: в каком порядке компилятор хочет вычислять, в таком будет вычислять. Да ещё и «i++» — не атомарное выражение, а «i:=i+1», то есть прибавить 1, а потом присвоить — и эти операции «прибавить» и «присвоить» компилятор может разнести далеко друг от друга, если так пожелает.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
gbg
@gbg
Любые ответы на любые вопросы
В случае с C++ мы имеем дело с неопределенным поведением. Здесь одна и та же переменная в пределах точки следования меняет свое значение дважды.

Так на C++ писать просто нельзя.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы