99 / 70 / 13
Регистрация: 15.12.2013
Сообщений: 455
1

Order of evaluation

02.07.2016, 00:37. Показов 2370. Ответов 35
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Всем привет. Никак не могу побороть 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)
-------------------------------------------------------------------------------------------
Побочный эффект (изменение левого аргумента) встроенного оператора присваивания и всех встроенных составных операторов присваивания расположены после вычисления значения (но не побочного эффекта) обоих аргументов (левого и правого) и расположены перед вычислением значения оператора присваивания (т.е. перед возвращением ссылки на измененный объект)


Но не нашел противоречий. Помогите понять это. Возможно на примере других выражений.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.07.2016, 00:37
Ответы с готовыми решениями:

Preprocessing evaluation order
Всем привет! Известно ли в каком порядке препроцессор обрабатывает файлы проекта? Из случая,...

Логические операции и правило Short Circuit Evaluation
Здравствуйте. Прошу помощи, так как мнения по данным вопросам расходятся 1.Какое значение будет...

HSQL запрос. Что не так? "from hiberdata.Order order where order.clientId=?"
public List loadOrdersByClientId(Integer clientId) { return getHibernateTemplate().find( 'from...

Function evaluation timed out
IEnumerable<Market> allMarkets = getAllMarkets();//count ~= 450 IEnumerable<int> neededIds = new...

35
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
02.07.2016, 16:40 21
Лучший ответ Сообщение было отмечено ASCII как решение

Решение

Author24 — интернет-сервис помощи студентам
Цитата Сообщение от ASCII Посмотреть сообщение
А вот там где комментарий вставил, туда компилятор может поместить еще какие-то инструкции по вычислению какой-то другой части выражения?
Вполне. В пределах "точки следования"
компилятор творить выполнять всякое разное, что,
по его компетентному мнению, не приведет к изменению результата
Правда, он еще вполне может выражения между собой местами менять,
что может напакостить сильно, но это уже другая тема

Добавлено через 1 минуту
Цитата Сообщение от ASCII Посмотреть сообщение
Безвредно, в смысле само по себе это не UB
Да, это нормальное выражение.
Цитата Сообщение от ASCII Посмотреть сообщение
когда мы это присваиваем объекту i?
Да, потому что не ясно становится что в каком порядке будет вычислено.
поэтому еще раз:
Цитата Сообщение от Croessmah Посмотреть сообщение
не нужно менять значение одного объекта несколько раз в одном выражении (expression, full-expression),
если нет явно выраженного порядка выполнения.
В i = i++ + 1, вы i меняете дважды, причем порядок изменений не определен.
0
99 / 70 / 13
Регистрация: 15.12.2013
Сообщений: 455
02.07.2016, 16:41  [ТС] 22
Цитата Сообщение от Croessmah Посмотреть сообщение
В пределах "точки следования"
secuence point rule вроде бы в С++11 уже нету? Его заменили на sequence before rule...
В следствии чего:

C++
1
i = ++i + 1; // undefined behavior (well-defined in C++11)
До С++11 было UB
http://en.cppreference.com/w/c... eval_order
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
02.07.2016, 16:41 23
Цитата Сообщение от ASCII Посмотреть сообщение
secuence point rule вроде бы в С++11 уже нету? Его заменили на sequence before rule...
Милицию в полицию тоже переименовали
Думаю, смысл высказывания ясен
1
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
02.07.2016, 16:42 24
ASCII, забей на компилятор. У него вообще большая свобода действий (в разумных пределах конечно). В стандарте речь не о нем:
The semantic descriptions in this International Standard define a parameterized nondeterministic abstract machine. This International Standard places no requirement on the structure of conforming implementations. In particular, they need not copy or emulate the structure of the abstract machine. Rather, conforming implementations are required to emulate (only) the observable behavior of the abstract machine as explained below.
1
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
02.07.2016, 16:52 25
Цитата Сообщение от ct0r Посмотреть сообщение
забей на компилятор
и на всё остальное тоже?
0
99 / 70 / 13
Регистрация: 15.12.2013
Сообщений: 455
02.07.2016, 17:00  [ТС] 26
Цитата Сообщение от Croessmah Посмотреть сообщение
Да, потому что не ясно становится что в каком порядке будет вычислено.
Цитата Сообщение от Croessmah Посмотреть сообщение
В i = i++ + 1, вы i меняете дважды, причем порядок изменений не определен.
Вот тут мы в плотную подошли к моменту, который меня на самом деле до сих пор путает.
Смотрите, имеем общее правило для вычисления операндов какого-либо оператора:

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)

Тут уже говорится несколько иначе. Первым делом вычисляются значения операндов оператора присваивания, то есть объект, которому присваивается и "результирующий объект", полученный после вычисления выражения, которое присваивается.

C++
1
a = B; /* где B - любое выражение, не обязательно идентификатор переменной */
Затем, только после вычисления значений этих операндов, происходит side effect левого аргумента.
И УЖЕ ПОСЛЕ ЭТОГО, происходит финальный value computation.

То есть тут получается все упорядочено оказывается? И это сбивает с толку. Ведь если следовать этим правилам (а другие правила тут не работают вроде-бы), то по моим умозаключениям получаем такую картину:

C++
1
2
int i = 0;
i = i++ + 1;
1 Этап - вычисляем операнды.
Поехали:

Первый вариант - сначала i, потом i++ + 1
i == 0 - вычислили, i - просто идентификатор, стоящий слева, не содержит никаких подвыражений.
i++ + 1 - опять, можем считать сначала i++, потом 1, или наоборот, но в данном случае, это не важно.
i++ == 0, i становится равной 1
получаем - 1 + 1.

Второй вариант - сначала i++ + 1, потом i
получим в итоге для i++ + 1 - 1 + 1
но на стадии вычисления i получим 1, но какая разница? Если это затирается?
Ничего не поменяется ведь...
Где-то тут чувствую я ошибаюсь

ОПЕРАНДЫ ВЫЧИСЛИЛИ.


2 Этап - side effect для левого операнда
Тут ясно все, все по порядку, вычислили операнды, и начинаем изменять объект i, присваиваем результат 1 + 1

Ну и финал - возврат ссылки на i, как результата выражения.

Вот и получается, что тут будет 2

Добавлено через 2 минуты
Цитата Сообщение от Croessmah Посмотреть сообщение
Милицию в полицию тоже переименовали
Думаю, смысл высказывания ясен
Смысл то ясен
На самом деле я хотел сказать о другом, что некоторые операции, которые в соответствии с правилом sequence point были UB, могут не являться таковыми в соответствии с правилом sequence before
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
02.07.2016, 17:02 27
Цитата Сообщение от ASCII Посмотреть сообщение
ОПЕРАНДЫ ВЫЧИСЛИЛИ.
Одна поправочка.
Для вычисления значений i++ + 1 достаточно копии i.
Фактически, именно она и будет операндом,
а когда будет вычислено остальное - уже пофигу,
значение i++ + 1 от этого не изменится.
1
99 / 70 / 13
Регистрация: 15.12.2013
Сообщений: 455
02.07.2016, 17:03  [ТС] 28
ct0r, ну не компилятор, так абстрактная машина, которая должна обеспечить наблюдаемый результат в соответствии с некими правилами. И вот как раз, почему эта машина делает именно так, а не иначе, я и хочу понять)
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
02.07.2016, 17:06 29
Croessmah, как вариант. Зачем нужно писать всякие ++ в выражениях, если это можно просто написать отдельно, что читабельнее и менее подвержено ошибкам? Разве что чужой быдлокод читать?
0
99 / 70 / 13
Регистрация: 15.12.2013
Сообщений: 455
02.07.2016, 17:06  [ТС] 30
Croessmah, про копию помню, я ее тут сознательно не упомянул, ибо
Цитата Сообщение от Croessmah Посмотреть сообщение
значение i++ + 1 от этого не изменится.
Что кстати и путает. Ведь если значение выражения не меняется, а порядок для оператора = задан.
То чем это отличается от, например

C++
1
i = 2;
Ведь все равно значение i затрется результатом выражения.
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
02.07.2016, 17:09 31
Цитата Сообщение от ct0r Посмотреть сообщение
Зачем нужно писать всякие ++ в выражениях, если это можно просто написать отдельно, что читабельнее и менее подвержено ошибкам?
Вы меня спрашиваете?
Я стараюсь даже типы в литералах указывать
C++
1
float f = 3.0f;//а не 3.0
Цитата Сообщение от ct0r Посмотреть сообщение
Разве что чужой быдлокод читать?
Часто делают просто для того, чтобы строчки экономить. А надо ли оно?

P.S. форум - отдельная эпопея, без строгих правил
0
99 / 70 / 13
Регистрация: 15.12.2013
Сообщений: 455
02.07.2016, 17:11  [ТС] 32
Цитата Сообщение от ct0r Посмотреть сообщение
Зачем нужно писать всякие ++ в выражениях, если это можно просто написать отдельно, что читабельнее и менее подвержено ошибкам?
Это конечно логично, но это с практической точки зрения. Я лишь преследую "понимание"
Дело в том, что читая Энтони Вильямса (я несколько книг читаю по многопоточности параллельно, кстати одну из которых мне советовали Вы и Убежденный), он начал объяснять про memory_order, то бишь про порядок доступа к памяти. А объясняя это, он вводит понятие "синхронизируется-с", которое базируется на правиле "расположено-перед", и вот из-за непонимания его, я не могу продолжить чтение

Добавлено через 1 минуту
Croessmah, а Вы чего не онлайн? Точно как бот
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
02.07.2016, 17:15 33
Цитата Сообщение от ASCII Посмотреть сообщение
а Вы чего не онлайн? Точно как бот
Ну, ежели я бот, то мне можно
1
99 / 70 / 13
Регистрация: 15.12.2013
Сообщений: 455
02.07.2016, 17:16  [ТС] 34
Цитата Сообщение от Croessmah Посмотреть сообщение
Ну, ежели я бот, то мне можно
Я просто вспомнил одну тему, в которой Вас ботом назвали
0
Неэпический
17869 / 10634 / 2054
Регистрация: 27.09.2012
Сообщений: 26,736
Записей в блоге: 1
02.07.2016, 17:18 35
Цитата Сообщение от ASCII Посмотреть сообщение
в которой Вас ботом назвали
И сделал это ct0r.
Совпадение? Не думаю.
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
02.07.2016, 17:29 36
Лучший ответ Сообщение было отмечено ASCII как решение

Решение

Цитата Сообщение от Croessmah Посмотреть сообщение
Вы меня спрашиваете?
Вдруг знаешь сокровенный смысл

Цитата Сообщение от ASCII Посмотреть сообщение
А объясняя это, он вводит понятие "синхронизируется-с", которое базируется на правиле "расположено-перед", и вот из-за непонимания его, я не могу продолжить чтение
На русском конкретно эту тему жесть читать, я сам, когда первый раз читал, не понял вообще ничего Пришлось брать англ вариант и поднимать дополнительные статьи. Вот например пара:
http://preshing.com/20130702/t... -relation/
http://preshing.com/20130823/t... -relation/

Цитата Сообщение от Croessmah Посмотреть сообщение
И сделал это ct0r.
1
02.07.2016, 17:29
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.07.2016, 17:29
Помогаю со студенческими работами здесь

Order by внутри order by
Добрый день, есть условно таблица с пользователями, у которых есть несколько сообщений,...

STM32 comStick Evaluation Board
Так и быть, расскажу, чего сейчас ковыряю :) Был на последней выставке в Нюрнберге Embeddid World....

CodeVisionAVR Evaluation V2.05.3a выдает ошибку
При построении hex-файла выдает ошибку "Error(s) occured during assembly" Подскажите...

Продам evaluation kit CY3267 Cypress
Новый. Только проверил на функционирование. 6000р. +79688645636


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

Или воспользуйтесь поиском по форуму:
36
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru