Форум программистов, компьютерный форум CyberForum.ru

Order of evaluation - C++

Восстановить пароль Регистрация
 
 
ASCII
 Аватар для ASCII
82 / 54 / 8
Регистрация: 15.12.2013
Сообщений: 370
Завершенные тесты: 2
02.07.2016, 00:37     Order of evaluation #1
Всем привет. Никак не могу побороть Order of evaluation. В статье на cppreference, приводятся примеры UB и уже на первом я застреваю и не понимаю почему именно так:

If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.
Если побочный эффект для скалярного объекта не упорядочен по отношению к другому побочному эффекту для этого же объекта - поведение не определено

C++
1
i = ++i + i++; // undefined behavior
Собственно тут я не знаю как мыслить. Как подобного рода UB находить в программах? Я пытался применять правила, которые описаны в Secuenced before rule, но ими я не смог объяснить UB приведенного выше примера.

Собственно для примера выше пытался применить правила:

2) The value computations (but not the side-effects) of the operands to any operator are sequenced before the value computation of the result of the operator (but not its side-effects).
-------------------------------------------------------------------------------------------
Вычисление значений (но не побочных эффектов) операндов любого оператора расположены перед вычислением значения оператора в целом (но не его побочного эффекта)

8) The side effect (modification of the left argument) of the built-in assignment operator and of all built-in compound assignment operators is sequenced after the value computation (but not the side effects) of both left and right arguments, and is sequenced before the value computation of the assignment expression (that is, before returning the reference to the modified object)
-------------------------------------------------------------------------------------------
Побочный эффект (изменение левого аргумента) встроенного оператора присваивания и всех встроенных составных операторов присваивания расположены после вычисления значения (но не побочного эффекта) обоих аргументов (левого и правого) и расположены перед вычислением значения оператора присваивания (т.е. перед возвращением ссылки на измененный объект)


Но не нашел противоречий. Помогите понять это. Возможно на примере других выражений.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.07.2016, 00:37     Order of evaluation
Посмотрите здесь:

C++ Описать структуру с именем Order
Описание структуры ORDER C++
Использование класса ORDER C++
Пояснение структуры ORDER C++
C++ Описать структуру с именем Order
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,919
Записей в блоге: 2
Завершенные тесты: 1
02.07.2016, 11:53     Order of evaluation #2
C++
1
i = ++i + i++; // undefined behavior
А попробуйте побыть на месте компилятора.
В какой последовательности вы выполните этот код?
ASCII
 Аватар для ASCII
82 / 54 / 8
Регистрация: 15.12.2013
Сообщений: 370
Завершенные тесты: 2
02.07.2016, 13:59  [ТС]     Order of evaluation #3
Croessmah, ну во-первых посмотрел бы на две части оператора =.

1) вычислил бы i (которая слева, value computation)
2) ++i + i++ ==> начал бы вычислять сперва значения операндов и наткнулся бы на:


4) The value computation of the built-in post-increment and post-decrement operators is sequenced before its side-effect.
-----------------------------------------------------------------------------------------------
Вычисление значение у встроенного постфиксного оператора инкремента расположено перед его побочным эффектом

5) The side effect of the built-in pre-increment and pre-decrement operators is sequenced before its value computation (implicit rule due to definition as compound assignment)
-----------------------------------------------------------------------------------------------
Тут тоже самое, только наоборот, побочный эффект перед вычислением значения


Но вроде как нету правила, которое мне (компилятору), диктует какой из операндов я должен вычислять первым.
Поэтому я могу поступить двумя способами:

1)

вычислить сперва ++i
вычислить i++
вычислить их сумму

2)

вычислить i++
вычислить ++i
вычислить их сумму

Но тут у оператора + операнды (++i) и (i++), поэтому вычислить значения операндов можно только с побочным эффектом, то есть выполняя операторы инкремента.

Таким образом, допустим если i изначально была равна 10

В первом варианте получается 23
Во втором варианте получается 22.

Еп, походу наличие двух вариантов у компиляторов и приводит к UB?
Какую-то длинную цепочку мыслей я построил...
Ferrari F1
Заблокирован
415 / 289 / 63
Регистрация: 27.01.2015
Сообщений: 1,931
Записей в блоге: 1
Завершенные тесты: 1
02.07.2016, 14:17     Order of evaluation #4
ASCII, как много времени уйдет, чтобы читать и вполне сразу понимать все эти статьи на английском?
ASCII
 Аватар для ASCII
82 / 54 / 8
Регистрация: 15.12.2013
Сообщений: 370
Завершенные тесты: 2
02.07.2016, 14:27  [ТС]     Order of evaluation #5
Если я правильно расписал пример выше, то как быть вот с этим?

C++
1
i = i++ + 1; // undefined behavior (but i = ++i + 1; is well-defined)
Добавлено через 3 минуты
Ferrari F1, это же от человека зависит, тут на мой взгляд играет роль:

1) Уровень знаний английского
2) Опыт в той области о которой читаешь
3) Ну и наверное целеустремленность

Я вот люблю докапываться до сути, наткнулся на такую проблему, теперь по справке со стандарта и cppreference пытаюсь досканально разобраться.

Добавлено через 2 минуты
Ferrari F1, а на счет сразу - трудно, тем более если только изучаешь английский, но по мере чтения на английском "выучиваются" слова и с каждым разом замечаешь, что уже читаешь и не задумываешься над переводом все дольше и дольше, не воспользовавшись переводчиком
Ferrari F1
Заблокирован
415 / 289 / 63
Регистрация: 27.01.2015
Сообщений: 1,931
Записей в блоге: 1
Завершенные тесты: 1
02.07.2016, 14:32     Order of evaluation #6
ASCII,
я просто думал, что все, кто выкладывают тут выдержки на английском, довольно неплохо его понимают при чтении информации технического плана (именно технического, а не разговорного или литературного, где могут содержаться всякие идиомы или двусмысленные обороты).

То есть это вполне нормально, что первое некоторое время придется с гугл переводчиком посидеть-попереводить каждое третье слово?
ASCII
 Аватар для ASCII
82 / 54 / 8
Регистрация: 15.12.2013
Сообщений: 370
Завершенные тесты: 2
02.07.2016, 14:38  [ТС]     Order of evaluation #7
Croessmah, вот тот пример, который я расписал, вроде бы объясняется этим
If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.
вполне понятно теперь, но с остальными то как?

Тут

C++
1
i = i++ + 1; // undefined behavior (but i = ++i + 1; is well-defined)
Вообще вроде над i side effect должен быть упорядочен?


8) The side effect (modification of the left argument) of the built-in assignment operator and of all built-in compound assignment operators is sequenced after the value computation (but not the side effects) of both left and right arguments, and is sequenced before the value computation of the assignment expression (that is, before returning the reference to the modified object)


То есть вычислить значения выражений i и i++ + 1, затем изменить i, затем сделать value computation для всего assignment выражения.

Добавлено через 1 минуту
Ferrari F1, пффф, я неделю назад чуть ли ни каждое слово гуглил. Сейчас вроде нормально читаю The Art of Multiprocessor Programming, а она только на английском. Конечно все равно приходится лезть в переводчик, но уже 1 раз на целый абзац.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,919
Записей в блоге: 2
Завершенные тесты: 1
02.07.2016, 15:12     Order of evaluation #8
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от ASCII Посмотреть сообщение
Какую-то длинную цепочку мыслей я построил...
Иногда это необходимо
Цитата Сообщение от ASCII Посмотреть сообщение
Еп, походу наличие двух вариантов у компиляторов и приводит к UB?
Ну вот видите, уже два варианта накопилось,
значит определить однозначно конечное значение тоже нельзя
Цитата Сообщение от Ferrari F1 Посмотреть сообщение
То есть это вполне нормально, что первое некоторое время придется с гугл переводчиком посидеть-попереводить каждое третье слово?
Я почти не знаю английский, как бы странно это не звучало
ASCII
 Аватар для ASCII
82 / 54 / 8
Регистрация: 15.12.2013
Сообщений: 370
Завершенные тесты: 2
02.07.2016, 15:15  [ТС]     Order of evaluation #9
Цитата Сообщение от Croessmah Посмотреть сообщение
Ну вот видите, уже два варианта накопилось,
значит определить однозначно конечное значение тоже нельзя
Спасибо за наставление на путь истинный , но как рассуждать с остальными примерами? Вот в частности с тем, который я привел в качестве следующего.
Ferrari F1
Заблокирован
415 / 289 / 63
Регистрация: 27.01.2015
Сообщений: 1,931
Записей в блоге: 1
Завершенные тесты: 1
02.07.2016, 15:18     Order of evaluation #10
Цитата Сообщение от Croessmah Посмотреть сообщение
Я почти не знаю английский, как бы странно это не звучало
Меня это обнадеживает)) Точно могу считать, что уметь понимать - это одно, а самому писать или говорить - совсем другое, куда сложнее)
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,919
Записей в блоге: 2
Завершенные тесты: 1
02.07.2016, 15:22     Order of evaluation #11
Цитата Сообщение от ASCII Посмотреть сообщение
но как рассуждать с остальными примерами?
Со всеми примерами рассуждайте так:
не нужно менять значение одного объекта несколько раз в одном выражении (expression, full-expression),
если нет явно выраженного порядка выполнения.
ASCII
 Аватар для ASCII
82 / 54 / 8
Регистрация: 15.12.2013
Сообщений: 370
Завершенные тесты: 2
02.07.2016, 15:26  [ТС]     Order of evaluation #12
Croessmah, это понятно, но ведь это не всегда так:

C++
1
i = ++i + 1; // well defined
Я преследую цель, понять, где можно так поступать, а где нет и почему именно так...
Вот казалось бы, разница между:

C++
1
i = ++i + 1; // well defined
и

C++
1
i = i++ + 1; // undefined behavior
Всего лишь в порядке value computation и side effect для операнда оператора +, но одно работает нормально, а другое UB...
Хотя и там и там в одном выражении есть 2 side effect'a для i.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,919
Записей в блоге: 2
Завершенные тесты: 1
02.07.2016, 15:53     Order of evaluation #13
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от ASCII Посмотреть сообщение
это понятно, но ведь это не всегда так
Поэтому я написал:
Цитата Сообщение от Croessmah Посмотреть сообщение
если нет явно выраженного порядка выполнения
Цитата Сообщение от ASCII Посмотреть сообщение
Вот казалось бы, разница между
В выражении i = ++i + 1; в любом случае инкремент будет выполнен при вычислении,
и уже потом будет выполнено присванивание, т.е. порядок вычисления задан.
А при
Цитата Сообщение от ASCII Посмотреть сообщение
C++
1
i = i++ + 1;
попробуйте снова встать на место компилятора.
В каком порядке должны идти присваивание и инкремент?
Сначала присвоить значение i, а потом увеличить значение на 1,
или же сначала увеличить значение, а потом выполнить присваивание?
Разложим выражение i = i++ + 1;, возьмем i равную 2:
C++
1
2
3
4
5
6
7
8
9
10
//раскладываем:
i++ + 1;//значение выражения равно 3, осталось выполнить инкремент и присваивание
//сделать так:
i = 3;
i += 1;
//и получить i равную 4
//или же сделать так:
i += 1;
i = 3;
//и получить i равную 3
http://rextester.com/RTWN92621
http://rextester.com/JDV61087
ASCII
 Аватар для ASCII
82 / 54 / 8
Регистрация: 15.12.2013
Сообщений: 370
Завершенные тесты: 2
02.07.2016, 16:13  [ТС]     Order of evaluation #14
Croessmah, А вот если рассмотреть такое выражение:

C++
1
i++ + 1;
Вопрос:

Согласно этому правилу - 2) The value computations (but not the side-effects) of the operands to any operator are sequenced before the value computation of the result of the operator (but not its side-effects).

Как будут получаться значения операндов оператора +?
А точней мне интересен такой момент:

1) Вычисляем 1 - все ясно, просто берем константу
2) Вычисляем i++ - ВОТ ТУТ, что тут произойдет? То есть операнд оператора + это подвыражение i++, чтобы вычислить его значение, его же необходимо полностью выполнить? То есть выполняем операцию, увеличиваем переменную и возвращаем ее прежнее состояние, согласно правилу выполнения постфиксного инкремента - это и будет процесс value computation для этого операнда? То есть невозможна такая ситуация, что компилятор просто прочтет значение i не выполняя ++?
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,919
Записей в блоге: 2
Завершенные тесты: 1
02.07.2016, 16:24     Order of evaluation #15
Цитата Сообщение от ASCII Посмотреть сообщение
чтобы вычислить его значение, его же необходимо полностью выполнить?
У Вас же в вычислениях дальше участвует копия i.
А инкремент будет выполнен где-то после.
И в данном случае, от этого "где-то" будет зависеть конечное значение i.
The value of a postfix ++ expression is the value of its operand. [ Note: the value obtained is a copy of the original value — end note ] The operand shall be a modifiable lvalue. The type of the operand shall be an arithmetic type or a pointer to a complete object type. The value of the operand object is modified by adding 1 to it, unless the object is of type bool, in which case it is set to true. [ Note: this use is deprecated, see Annex D. — end note ] The value computation of the ++ expression is sequenced before the modification of the operand object. With respect to an indeterminately-sequenced function call, the operation of postfix ++ is a single evaluation. [ Note: Therefore, a function call shall not intervene between the lvalue-to-rvalue conversion and the side effect associated with any single postfix ++ operator. — end note ] The result is a prvalue. The type of the result is the cv-unqualified version of the type of the operand. See also 5.7 and 5.17.
ASCII
 Аватар для ASCII
82 / 54 / 8
Регистрация: 15.12.2013
Сообщений: 370
Завершенные тесты: 2
02.07.2016, 16:25  [ТС]     Order of evaluation #16
Цитата Сообщение от Croessmah Посмотреть сообщение
А так постинкремент будет выполнен где-то после.
То есть после "операции" value computation операнда i++, значение i не изменится что ли?
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,919
Записей в блоге: 2
Завершенные тесты: 1
02.07.2016, 16:28     Order of evaluation #17
Цитата Сообщение от ASCII Посмотреть сообщение
То есть выполняем операцию, увеличиваем переменную и возвращаем ее прежнее состояние
Возвращаем прежнее состояние, всё остальное - когда придется.

Добавлено через 39 секунд
Цитата Сообщение от ASCII Посмотреть сообщение
значение i не изменится что ли?
Нет. Оно изменится, скорее всего, где-то уже после выражения в котором стоит постинкремент:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
i = 2;
i2 = i;
//варианты
x = i2 + 1
++i;
i = x;
//или
x = i2 + 1
i = x;
++i;
//или (результат аналогичен первому варианту)
++i;
x = i2 + 1
i = x;
ASCII
 Аватар для ASCII
82 / 54 / 8
Регистрация: 15.12.2013
Сообщений: 370
Завершенные тесты: 2
02.07.2016, 16:31  [ТС]     Order of evaluation #18
Цитата Сообщение от Croessmah Посмотреть сообщение
Возвращаем прежнее состояние, всё остальное - когда придется.
Ну то что прежнее состояние вернется то понятно, но вот не могу понять, что значит "когда придется"?
Получается когда компилятор вычисляет значения операндов, он не выполняет операции? В конкретном примере на стадии вычисления значения подвыражения i++ он просто читает значение i и не выполняет операцию?
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,919
Записей в блоге: 2
Завершенные тесты: 1
02.07.2016, 16:32     Order of evaluation #19
Цитата Сообщение от ASCII Посмотреть сообщение
и не выполняет операцию?
выполняет, но после, где конкретно - после выражения, конкретнее - не ясно.
Вот от таких "после", "где-то", "как-то" Ваш код не должен зависеть.
То есть i = i++ + 1;
нужно заменить, например, на
C++
1
2
t = i++;
i = t + 1;
здесь порядок задан явно.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.07.2016, 16:38     Order of evaluation
Еще ссылки по теме:

Создать класс Order C++
C++ Preprocessing evaluation order

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
ASCII
 Аватар для ASCII
82 / 54 / 8
Регистрация: 15.12.2013
Сообщений: 370
Завершенные тесты: 2
02.07.2016, 16:38  [ТС]     Order of evaluation #20
C++
1
2
3
4
//варианты
x = i2 + 1
/* ЗДЕСЬ, СМ НИЖЕ */
++i;
А вот там где комментарий вставил, туда компилятор может поместить еще какие-то инструкции по вычислению какой-то другой части выражения?

Добавлено через 1 минуту
Цитата Сообщение от Croessmah Посмотреть сообщение
выполняет, но после, где конкретно - после выражения, конкретнее - не ясно.
Вот от таких "после", "где-то", "как-то" Ваш код не должен зависеть.
То есть i = i++ + 1;
нужно заменить, например, на
C++
1
2
t = i++;
i = t + 1;
здесь порядок задан явно.
Туповат я походу.

Добавлено через 1 минуту
Но ведь само по себе выражение

C++
1
i++ + 1;
Безвредно, в смысле само по себе это не UB, оно становится таковым, когда мы это присваиваем объекту i? Новое выражение в смысле, i = i++ + 1
Yandex
Объявления
02.07.2016, 16:38     Order of evaluation
Ответ Создать тему
Опции темы

Текущее время: 16:28. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru