powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Порядок вычисления
110 сообщений из 110, показаны все 5 страниц
Порядок вычисления
    #38822608
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У Саттера опрос http://herbsutter.com/2014/12/01/a-quick-poll-about-order-of-evaluation/

Код: plaintext
1.
2.
3.
4.
std::vector<int> v = { 0, 0 };
int i = 0;
v[i++] = i++;
std::cout << v[0] << v[1] << endl;


В текущей версии стандарта "v[i++] = i++" - это UB (и даже не один).
Вопрос: какой должна быть логика выполнения данного выражения, если бы мы захотели убрать этот конкретный вид UB в стандарте.
Т.е. какой результат должна печатать программа: 00, 01, 10, или оставить UB?
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822630
Вася Уткин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В идеале, чтобы такие выражения всегда компилятор отлавливал с comile error, но думаю что это вряд ли возможно.

А так, наверное 00, это проще было бы понимать. Сначала беруться исходные значения, а уже после отрабатывают все эти obj++:
Т.е.
Код: plaintext
1.
v[i++] = i++;


превращается в:
Код: plaintext
1.
2.
v[i] = i;
i++; i++;



А сами как считаете?
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822639
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще-то порядок и приоритеты опираций описаны в доке. Только я их не помню. Так никогда не пишу
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822642
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonid KudryavtsevВообще-то порядок и приоритеты опираций описаны в доке. Только я их не помню. Так никогда не пишу
Тут тема вообще не про это.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822644
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyТ.е. какой результат должна печатать программа: 00, 01, 10, или
оставить UB?
Проголосовал за 01, поскольку вычислять все постинкременты перед всем остальным уж больно
геморройно и неочевидно.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822650
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сам я считаю что оператор присвоения должен быть sequence point.
Т.е. сначала вычисляется левая часть, потом правая, потом выполняется присвоение.

Код: plaintext
1.
2.
3.
4.
//v[i++] = i++;

T& temp = v[i++];
temp = i++;



Т.е. ответ 10
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822659
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyУ Саттера опрос http://herbsutter.com/2014/12/01/a-quick-poll-about-order-of-evaluation/

Код: plaintext
1.
2.
3.
4.
std::vector<int> v = { 0, 0 };
int i = 0;
v[i++] = i++;
std::cout << v[0] << v[1] << endl;


В текущей версии стандарта "v[i++] = i++" - это UB (и даже не один).
Вопрос: какой должна быть логика выполнения данного выражения, если бы мы захотели убрать этот конкретный вид UB в стандарте.
Т.е. какой результат должна печатать программа: 00, 01, 10, или оставить UB?

Если не undefined behaviour, то 10. Точно не 00
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822662
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А что вообще хотел автор получить в векторе?

Код: plaintext
1.
v[i++] = i++;



Голосую за "Unspecified (one of the first three options, but could be different on different compilers)"
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822663
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
думаю, стоит оставить UB, а в целом, согласен с
Вася УткинВ идеале, чтобы такие выражения всегда компилятор отлавливал с compile error, но думаю что это вряд ли возможно.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822692
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyТ.е. сначала вычисляется левая часть, потом правая, потом
выполняется присвоение.
Почему сначала левая? Предположим, вычисление каждой из частей приводит к ошибкам
исполнения (неважно каким). Почему пользователь должен получить ошибку связанную с
вычислением левой части, а не правой?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822701
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyСам я считаю что оператор присвоения должен быть sequence point.
Т.е. сначала вычисляется левая часть, потом правая, потом выполняется присвоение.порядок вычисления аргументов функции не определён, жеж, а тут получается, что мы взяли, и сказали, что вот именно для оператора присваивания - определён. нехорошо как то, имхо ))
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822736
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
egorychпорядок вычисления аргументов функции не определён, жеж, а тут получается,
что мы взяли, и сказали, что вот именно для оператора присваивания - определён. нехорошо
как то, имхо ))
Ещё со времён K&R оператор присваивания вычисляется справа налево.

PS: Порядок вычисления аргументов функции определяется соглашением о вызове.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822753
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov
>> Ещё со времён K&R оператор присваивания вычисляется справа налево.
в С операторы - не функции, K&R не имеют отношения к C++, не видишь не стыковки? ))

>> PS: Порядок вычисления аргументов функции определяется соглашением о вызове.
пруф давай. Соглашение о вызове ничего не говорит о порядке вычисления аргументов функции, а говорит куда их класть в каком порядке.

Кстати, развивая твою мысль, если я напишу __cdecl operator=( ... ) будет один результат для исходного вопроса, если __pascal operator=( ... ), то другой, а если __fastcall operator=( ... ), то третий, так? имхо, это UB
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822775
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
egorychв С операторы - не функции, K&R не имеют отношения к C++, не видишь не
стыковки? ))
Операторы возвращают значение? Возвращают. Значит - функции.

egorychКстати, развивая твою мысль, если я напишу __cdecl operator=( ... ) будет
один результат для исходного вопроса, если __pascal operator=( ... ), то другой, а если
__fastcall operator=( ... ), то третий, так? имхо, это UB
У функции оператора присваивания всего один аргумент. Его совершенно всё равно с какой
стороны вычислять.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822797
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonid KudryavtsevВообще-то порядок и приоритеты опираций описаны в доке. Только я их не помню. Так никогда не пишу

Приоритеты операций не имеют к обсуждаемому вопросу ни малейшего отношения.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822847
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Попробовал на GCC: (GNU) 4.8.1.

Код: sql
1.
1 0
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822908
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
egorychпорядок вычисления аргументов функции не определён, жеж, а тут получается, что мы взяли, и сказали, что вот именно для оператора присваивания - определён. нехорошо как то, имхо ))
Так тут как раз речь идет чтобы задать определенное поведение.
Ничего страшного в исключениях из правил я не вижу, если они облегчают программирование.
То, что я предлагаю, хорошо тем, что в каком порядке код записан - так и выполняется.
Все остальные варианты поведения сложнее читаются и никаких преимуществ не имеют.

maytonПопробовал на GCC: (GNU) 4.8.1.

Код: sql
1.
1 0


Умные люди. Понимают толк :)
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822915
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovЕщё со времён K&R оператор присваивания вычисляется справа налево.
Это утверждение относится к приоритету и ассоциативности операций, а не к порядку вычисления вообще.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822922
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyЭто утверждение относится к приоритету и ассоциативности операций,
а не к порядку вычисления вообще.
Но приоритет в данном случае вытекает из естественного порядка вычисления операндов. При
вычислении цепочки присваиваний слева направо требуется либо накапливать стэк указателей
на значения либо уходить в рекурсию. Порядок справа налево разворачивается в тривиальный
итерационный процесс.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822931
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyНичего страшного в исключениях из правил я не вижу, если они облегчают программирование.я тоже, в целом, мне только кажется, что "устандартивание" )) этого кейса будет стимулировать писать код в подобном стиле, а это мне не очень нравится, пусть бы было бы UB, что значит, что так писать не надо.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822943
Вася Уткин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly MoskovskyНичего страшного в исключениях из правил я не вижу, если они облегчают программирование.
То, что я предлагаю, хорошо тем, что в каком порядке код записан - так и выполняется .
Убедили, действительно, просто оператор присвоения сделать sequence point.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822944
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakov,

Опять же вы не совсем то описываете.
Приоритет операций существует только при синтаксическом анализе.
Проблема затронутая в данном топике возникает на более позднем этапе, когда синтаксическое дерево уже построено и теперь код надо выполнить.
С точки зрения выполнения, присвоение - это вызов функции с двумя аргументами. В каком порядке вычислять аргументы - не имеет значения, главное чтобы все аргументы были готовы на момент вызова.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822947
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
egorychAnatoly MoskovskyНичего страшного в исключениях из правил я не вижу, если они облегчают программирование.я тоже, в целом, мне только кажется, что "устандартивание" )) этого кейса будет стимулировать писать код в подобном стиле, а это мне не очень нравится, пусть бы было бы UB, что значит, что так писать не надо.
Было-бы правильно чтобы чем новее версия при компилляции выдавала WARNING.
И чем новее - тем настойчивее. И правила - жёстче.

Заигнорил? Сам виноват. Сам себе злобный буратино.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822948
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
egorych"устандартивание" )) этого кейса будет стимулировать писать код в подобном стиле
В таком случае надо запретить много чего, чтоб стиль не портить.
Например убрать тернарный оператор, чтобы SashaMercury не злоупотрелбял им
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822951
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonБыло-бы правильно чтобы чем новее версия при компилляции выдавала WARNING.
И чем новее - тем настойчивее. И правила - жёстче.
К сожалению, в реальных программах этот кейс встречается в основном в неявном виде, типа этого.
Код: plaintext
1.
2.
int& j = i; // где-то в другой функции
v[j++] = i++;


Отследить алиасинг не всегда возможно.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822952
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovsky, надеюсь что этот кейс настолько редкий
чтобы не ощущать damage на уровне статистики.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822953
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyС точки зрения выполнения, присвоение - это вызов функции с двумя аргументами. В каком порядке вычислять аргументы - не имеет значения, главное чтобы все аргументы были готовы на момент вызова.Тогда, единственным логичным выбором остаётся "неопределённое поведение".
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822958
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovAnatoly MoskovskyТогда, единственным логичным выбором остаётся "неопределённое поведение".
Это было бы так если бы устранение UB вносило бы оверхед.
Но по факту легко задать определенное поведение для случая присвоения не внося оверхед.
А значит это надо сделать.
Потому что как я выше писал встречаются нетривиальные и вполне непротиворечивые варианты этого кейса, и наказывать программиста за непреднамеренное применение - бессмысленно.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822991
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakovegorychпорядок вычисления аргументов функции не определён, жеж, а тут получается,
что мы взяли, и сказали, что вот именно для оператора присваивания - определён. нехорошо
как то, имхо ))
Ещё со времён K&R оператор присваивания вычисляется справа налево.

PS: Порядок вычисления аргументов функции определяется соглашением о вызове.


это неправда. две неправды.

= выполняется справа налево, а не вычисляется.

параметры передаются в определенном порядке, а не вычисляются.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822992
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry Sibiryakovegorychв С операторы - не функции, K&R не имеют отношения к C++, не видишь не
стыковки? ))
Операторы возвращают значение? Возвращают. Значит - функции.



Дима! Ну ты же грамотный человек, зачем такую хрень пишешь?
...
Рейтинг: 0 / 0
Порядок вычисления
    #38822994
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я сам за Undefined. Так прямо Гербу и отписал...
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823017
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyНапример убрать тернарный оператор, чтобы SashaMercury не злоупотрелбял им не, я тоже люблю тернарный оператор, святое не трожь!
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823018
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyВ таком случае надо запретить много чего, чтоб стиль не портить.я бы C-style каст бы запретил бы уже ))
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823031
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyЭто было бы так если бы устранение UB вносило бы оверхед.
Но по факту легко задать определенное поведение для случая присвоения не внося оверхед.
А значит это надо сделать.Устранить неопределённость, значит разрешить использование.Потому что как я выше писал встречаются нетривиальные и вполне непротиворечивые варианты этого кейса, и наказывать программиста за непреднамеренное применение - бессмысленно.Неправда.
Если я создал "псевдоним", то на меня же ложиться и ответственность за "множественное использование".
"Сложно отследить" - не оправдание. Это жестко и не совсем практично, но именно такой подход является единственно правильным.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823033
Alca
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Посчему здесь UB?
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823044
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyК сожалению, в реальных программах этот кейс встречается в основном в неявном виде, типа этого.
Код: plaintext
1.
2.
int& j = i; // где-то в другой функции
v[j++] = i++;

Отследить алиасинг не всегда возможно.Толку убирать UB, если простое переписывание "подозрительного" кода на "определённый":
Код: sql
1.
2.
3.
4.
int& j = i; //где-то там
v[j] = i;
i += 1;
j += 1;

ставит нас на грабли?
Может просто не использовать замысловатые инкременты для переменных "вне подконтрольной области"?
Тем более, что если уж бороться за эффективность, то постинкремент должен быть предан анафеме
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823128
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovТолку убирать UB, если простое переписывание "подозрительного" кода на "определённый"
Толк в том чтобы помочь программисту, а не мешать.
Когда есть код с такой проблемой то это почти наверняка баг.
И разрешать каждой платформе по разному выполнять этот код - это затрудняет поиск бага.
Хотя ничего не мешает именно в данном конкретном случае задать определенное поведение (любое).
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823168
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyТолк в том чтобы помочь программисту, а не мешатьПрограммирование всё больше и больше становится производством кода. На любом производстве есть правила техники безопасности, которые могут мешать и мешают эффективному производству.
В данном конкретном случае я бы сформулировал примерно так: "более одного выражения с побочным эффектом в одном операторе - неопределённое поведение".
Да, можно тем или иным способом доопределить поведение компилятора, но "потрудитесь излагать яснее, кто на ком стоял". Нет проблемы превратить невнятное:
Код: sql
1.
2.
3.
std::vector<int> v = { 0, 0 };
int i = 0;
v[i++] = i++;

в более определённое:
Код: sql
1.
v[i] = i, i++;

или в любой другой из, возможно подразумевавшихся, вариантов:
Код: sql
1.
v[i] = i, ++i;

Ни пальцы не сотрутся, ни ум за разум не зайдёт.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823334
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AlcaПосчему здесь UB?

По современному стандарту модификация одной и той же переменной более одного раза до точки следования является UB.
Кажется, так.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823341
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyBasil A. SidorovТолку убирать UB, если простое переписывание "подозрительного" кода на "определённый"
Толк в том чтобы помочь программисту, а не мешать.
Когда есть код с такой проблемой то это почти наверняка баг.
И разрешать каждой платформе по разному выполнять этот код - это затрудняет поиск бага.
Хотя ничего не мешает именно в данном конкретном случае задать определенное поведение (любое).

Я лично резко против такого подхода.

В приведённом в оригинальном посте примере написан код, которого вообще не должно быть в нормальной программе.
В чём преимущество написать этот код именно так ? НИ В ЧЁМ, это просто дешёвые понты старого С-шника. Типа -- а и вот так заверну.

Так что UB.

Там кстати в оригинальном посте даже картинку запостили:
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823345
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov....в более определённое:
Код: sql
1.
2.
v[i] = i, i++;
v[i] = i, ++i;

Ни пальцы не сотрутся, ни ум за разум не зайдёт.
У кого как. У меня заходит.

ВикипедияIn the C and C++ programming languages, the comma operator (represented by the token ,) is a binary operator that evaluates its first operand and discards the result, and then evaluates the second operand and returns this value (and type).

в чем сакральный смысл записи "i,i++" ?
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823353
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonid KudryavtsevBasil A. Sidorov....в более определённое:
Код: sql
1.
2.
v[i] = i, i++;
v[i] = i, ++i;

Ни пальцы не сотрутся, ни ум за разум не зайдёт.
У кого как. У меня заходит.

ВикипедияIn the C and C++ programming languages, the comma operator (represented by the token ,) is a binary operator that evaluates its first operand and discards the result, and then evaluates the second operand and returns this value (and type).

в чем сакральный смысл записи "i,i++" ?

Тут -- ни в чём. Можно заменить на ' ; '
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823420
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А мне показалось смысл в том, что бы "взорвать мозг".

Вообще, мне кажется, весь топик этому посвящен. Какой-то топик для брюнеток, которые хотят уметь "взрывать мозг" как блондинки (блондинки это с рождения умеют). Только не понятно, при чем тут C и компилятор. IMHO
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823465
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Автор пишет:

авторMy question is not what it might print under today’s C++ rules.
The third line runs afoul of two different categories of undefined
and unspecified behavior.

Rather, my question is what you would like the result to be.
Please let me know.

Поправьте меня в моём английском если что.

Но он спрашивает - "Какой-бы результат вам хотелось-бы получить на выходе?"
Это философия. Дискурс. Мозговой штурм. Сбор мнений соц-опрос.

Так я думаю.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823626
Вася Уткин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
MasterZivAlcaПосчему здесь UB?

По современному стандарту модификация одной и той же переменной более одного раза до точки следования является UB.
Кажется, так.
Кстати, а можно как-то настроить msvc, gcc или clang отлавливать такие warning-и, чтобы компиляция дальше не проходила?
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823628
Вася Уткин
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Basil A. SidorovТем более, что если уж бороться за эффективность, то постинкремент должен быть предан анафеме
А почему бы действительно не отказаться от постинкремента, есть ли вообще случаи когда без него не обойтись или он заметно что-то облегчает?
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823643
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivВ приведённом в оригинальном посте примере написан код, которого вообще не должно быть в нормальной программе.
В чём преимущество написать этот код именно так ? НИ В ЧЁМ, это просто дешёвые понты старого С-шника. Типа -- а и вот так заверну.
В оригинальном посте показан минимальный пример демонстрирующий проблему в явном виде.
В реальных программах проблема не так очевидна.

Например, недавно тут обсуждался код, против которого ни у кого не возникало никаких возражений:
Код: plaintext
1.
*str1++ = *str2++;



Но тут возможна та же самая проблема, если str1 является ссылкой на str2, потому что данный код эквивалентен такому:
Код: plaintext
1.
2.
int& i = j;
str1[i++] = str2[j++];


Это баг, что нет проверки на равенство, но из-за UB его можете не сразу заметить.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823657
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovsky
Например, недавно тут обсуждался код, против которого ни у кого не возникало никаких возражений:
Код: plaintext
1.
*str1++ = *str2++;




Не надо преувеличивать.
Часто ты используешь ссылки на указатели ?
Да ещё чтобы писать в них можно было ...

Вообще, это код из С, там ссылок нет.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823658
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovsky
Но тут возможна та же самая проблема, если str1 является ссылкой на str2, потому что данный код эквивалентен такому:
Код: plaintext
1.
2.
int& i = j;
str1[i++] = str2[j++];


Это баг, что нет проверки на равенство, но из-за UB его можете не сразу заметить.

Да, и где тут UB ? Его тут нет.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823677
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivДа, и где тут UB ? Его тут нет.
Учите матчасть :)
MasterZivНе надо преувеличивать.
Часто ты используешь ссылки на указатели ?
Не вижу смысла спорить.
Сейчас в коде нет ссылок, а потом пришел другой программист и добавил ссылки. И приплыли.
Баги будут всегда. Вне зависимости от вашего желания и доброй воли.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823693
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Коллеги. Давайте на не повышать градус эмоций.

Об недостатках алгебры инкрементов писал еще старый пьяница и музыкант
профессор Николай Вирт(ов). Что тут еще добавить.

Лучше давайте формализуем такие формы которые требуют
гарантии эквивалентного преобразования в форму без
использования оных стрёмных операций.

Если разработчик умеет и делает трансформацию
этого кода

Код: plaintext
1.
str1[i++] = str2[i++];



в код без пост-икремента, и преобразование - строго однозначно
то проблемы - нет.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823705
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Копировать из одной строки в другую... на одном и том же указателе... это жестко

Я всегда был противником ссылок. Ровно из-за того, что код становится совершенно не читабельным. Кто в здравом уме, может подумать, что в конструкции вида:

*str1++ = *str2++;

str1 и str2 это даже не просто указатель на одну и ту же строку. А вообще, один и тот же указатель, но пропихнутый в код через ссылку. Взрыв мозга.

Но это проблема не компилятора, это проблема цвета волос. Предлагаю просто запретить программистам быть блондинками, красить волосы в светлые тона, делать меллирование. Естественным блондинкам от рождения, конечно, за счет фирмы придется оплатить черную краску и услуги хорошего салона. Должно помочь. IMHO
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823715
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мартин Фаулер ввёл хороший термин. Код с "душком".
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823720
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonstr1[i++] = str2[i++];
А этот код имеет какой нибудь прикладной смысл? "копирование одной строки в другую через символ. Без проверки, что в строке может быть нечетное кол-во символов"?

Я лично бы написал просто (для тупо копирования):

Код: sql
1.
2.
str1[ i ] = str2[ i ];
i++;



код (копирование через один символ)

Код: sql
1.
2.
3.
str1[ i ] = str2[ i ];
i++;
i++;



конечно тоже имеет право на жизнь, но зато сразу видно, что проверка на неожиданное окончания строки отстутствует.

Смысл лепить все в одну строку - не вижу вообще. Когда все в одной строке, такие выражения значительно сложнее отлаживать IMHO & AFAIK
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823725
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати да. Дебаггер видит это как 1 степ.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823733
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чуваки, еще раз говорю - данный код пишется не намеренно, а в результате бага.
Соответственно прикладного смысла в нем нет, и переписать его тоже нельзя - сначала его надо найти.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823737
egorych
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyЧуваки, еще раз говорю - данный код пишется не намеренно, а в результате бага.
Соответственно прикладного смысла в нем нет, и переписать его тоже нельзя - сначала его надо найти.но если такой стиль узаконить, то найти баг будет ещё сложнее, не?

P.S. Возможно, выходом было бы, действительно, уход от UB, но с варнингом, по возможности. Так будут и овцы целы, и волки сыты, кмк
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823739
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Найти в одной строке кода два инкремента. Далее - по обстановке. Остановить compile/build. Выдать варнинг.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823743
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonКоллеги. Давайте на не повышать градус эмоций.

Об недостатках алгебры инкрементов писал еще старый пьяница и музыкант
профессор Николай Вирт(ов). Что тут еще добавить.


Ну и как он кончил ? Плохо он кончил -- паскаль написал.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823745
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonМартин Фаулер ввёл хороший термин. Код с "душком".

Но этот код (strcpy) БЕЗ душка.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823754
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivmaytonМартин Фаулер ввёл хороший термин. Код с "душком".

Но этот код (strcpy) БЕЗ душка.

Хех... ну ладно. Укусил .
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823822
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Действительно, K&R приводят в пример функцию

Код: plaintext
1.
2.
3.
4.
void strcpy(char *s, char *t)
{
    while (*s++ = *t++);
}


K&R p. 104Приращение s и t здесь осуществляется в управляющей части цикла. Значением *t++ является символ, на
который указывает переменная t перед тем, как ее значение будет увеличено; постфиксный оператор ++ не
изменяет указатель t, пока не будет взят символ, на который он указывает. То же в отношении s: сначала
символ запомнится в позиции, на которую указывает старое значение s, и лишь после этого значение
переменной s увеличится. Пересылаемый символ является одновременно и значением, которое
сравнивается с '\0' . В итоге копируются все символы, включая и заключительный символ '\0'.

Предлагаю рассмотреть такой участок кода:
Код: plaintext
1.
2.
3.
4.
5.
char buf[]="abcdefg";
char* s1=buf+3;//"defg";
char* s2=buf;//"abcdefg"
strcpy(s1,s2);//1
strcpy(s2,s1);//2


Понятно что в обоих случаях, мы ничего хорошего не получим. Собственно потому в стандарте, в прототипе функции мы можем видеть restrict-квалификаторы

ISO/IEC 9899:201x7.24.2.3 The strcpy function
Synopsis
1
Код: plaintext
1.
2.
3.
#include <string.h>
char *strcpy(char * restrict s1,
const char * restrict s2);

Description
2 The strcpy function copies the string pointed to by s2 (including the terminating null
character) into the array pointed to by s1. If copying takes place between objects that
overlap, the behavior is undefined.
Returns
3 The strcpy function returns the value of s1.

По коду

Код: plaintext
1.
2.
3.
4.
std::vector<int> v = { 0, 0 };
int i = 0;
v[i++] = i++;
std::cout << v[0] << v[1] << endl;



если бы нам сказали, что не должно быть UB, хоть ты тресни, я подумал ещё немного. Возможно стоит вести себя так-же как в примере выше, и на выходе мы получим 00 (знаю что недавно исключил такой вариант). Вообщем у меня такой вопрос, зачем нужен такой код, какая от него практическая выгода ? Думаю что особой выгоды нет, и мы просто пытаемся решить вопрос о том, что было бы если бы мы вводили закон касаемо такого поведения. У меня нет аргументов ни за, ни против того, что такой закон нужен. Приведите их пожалуйста :)


Basil A. Sidorov Программирование всё больше и больше становится производством кода. На любом производстве есть правила техники безопасности, которые могут мешать и мешают эффективному производству.

Почему вы так считаете ?
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823829
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryBasil A. Sidorov Программирование всё больше и больше становится производством кода. На любом производстве есть правила техники безопасности, которые могут мешать и мешают эффективному производству.

Почему вы так считаете ?
По факту так и есть. Производство. Я каждый день делаю code review десятков а то и сотен строк кода. И если-бы не
механизмы FindBug, Cobertura, JUnit, Mockito я-бы просто потонул. Автоматизация проверки кода гарантирует
хотя-бы отсутствие ляпов и неоднозначностей подобно пост-инкрементам.

По поводу движения двух указателей в strcpy я не имею ничего против. Но при этом я оглядываюсь
на прото-ассемблерную семантику "C". Этот исходник написан в "духе" C и соответствует правильным
трендам.

В Java подобный код я не пропущу. Заверну на доработку.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823833
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А, к чему я рассуждал про strcmp то. К тому, что и Илья и Анатолий в данном споре оба правы, потому что один видимо говорил про то что эта функция полностью корректна подразумевая ограничения наложенные на входные параметры, а второй рассмотрел общий случай данного кода :)
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823843
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonВ Java подобный код я не пропущу. Заверну на доработку.
У меня правила жестче. Я джаву целиком заворачиваю
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823844
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А я - либерал.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38823976
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyУ меня правила жестче. Я джаву целиком заворачиваю
Почему-то это мне напомнило М.Булгакова "Новый способ распространения книг"

В книжном складе не было ни одного покупателя, и приказчики уныло стояли за прилавками. Звякнул звоночек, и появился гражданин с рыжей бородой веером. Он сказал:

— Драсьте…

— Чем могу служить? — обрадованно спросил его приказчик.

— Нам бы гражданина Лермонтова сочинение,— сказал гражданин, легонько икнув.

— Полное собрание прикажете?

Гражданин подумал и ответил:

— Полное. Пудиков на пятнадцать-двадцать.

У приказчика встали волосы дыбом.

— Помилте, оно и всё-то весит фунтов пять, не более!

— Нам известно,— ответил гражданин,— постоянно его покупаем. Заверните экземплярчиков пятьдесят. Пущай ваши мальчики вынесут, у меня тут ломовик дожидается.

Приказчик брызнул по деревянной лестнице вверх и с самой крайней полки доложил почтительно:

— К сожалению, всего пять экземпляров осталось.

— Экая жалость,— огорчился покупатель.— Ну давайте хучь пять. Тогда, милый человек, соорудите мне ещё «Всемирную историю».

— Сколько экземпляров? — радостно спросил приказчик.

— Да отвесь полсотенки…

— Экземплярчиков?

— Пудиков.

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

— Вася! Полка 15-а. Скидай «Всемирную», всю как есть. Не прикажете ли в переплётах? Папка, тиснённая золотом…

— Не требуется,— ответил покупатель.— Нам переплёты ни к чему. Нам главное, чтоб бумага была скверная.

Приказчики опять ошалели.

— Ежели скверная,— нашёлся наконец один из них,— тогда могу предложить сочинения Пушкина и издание Наркомзема.

— Пушкина не потребуется,— ответил гражданин,— он с картинками, картинки твёрдые. А Наркомзема заверни пудов пять на пробу.

Через некоторое время полки опустели, и сам заведующий вежливо выписывал покупателю чек. Мальчики, кряхтя, выносили на улицу книжные пачки. Покупатель заплатил шуршащими белыми червонцами и сказал:

— До приятного свидания.

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

— Крупного,— ответил с достоинством покупатель,— селёдками торгуем. Наше вам.

И удалился.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824001
Фотография TPAKTOPA
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Раньше делал так, даже на более сложных выражениях - работало. И в C# работало.

Код: plaintext
1.
2.
3.
4.
5.
std::vector<int> v = { 0, 0 };
int i = 0;
v[i] = i++;
v[i] = i++;
std::cout << v[0] << v[1] << endl;



Результат 01

Но уже давно не делаю, потому что если позже сделать copy/paste кода и редактировать, можно по ошибке два раза в строке сделать i++
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824101
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyСоответственно прикладного смысла в нем нет, и переписать его тоже нельзя - сначала его надо найти.Ну, допустим пробьют стену головой - нет, типа, накладных расходов.
Завтра напишут код без инкрементов и получат "изменившееся поведение".
Найти ошибку тоже будет нельзя, т.к. не зная места ошибки невозможно сказать: из-за UB она или из-за незнания хитровывернутых мест стандарта.
Что принципиального меняется в поиске места ошибки? Чем поможет то, что теперь ошибка одинакова на всех системах?
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824183
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonid Kudryavtsevв чем сакральный смысл записи "i,i++" ?Ни в чём. Просто пример, что выёживаться можно по разному.
Можно? Да. Нужно? Нет.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824202
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть, кстати, ещё один, хотя и (пока) абстрактный довод против "доопределения побочных эффектов".
Без побочных эффектов, код вида:
Код: sql
1.
v[i+j] = i - j;

допускает параллельное вычисление, что (потенциально) позволяет компилятору генерить более быстрый код.
Если "доопределять UB", то правила параллельной кодогенерации станут сложнее. Возникнут те самые накладные расходы, которых "раньше не было".

P.S. Пример, разумеется, тупой и, вероятно, без доп.усилий будет обработан суперскалярным конвейером более-менее современных процессоров, но общий посыл от этого не меняется.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824219
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonSashaMercuryпропущено...


Почему вы так считаете ?
По факту так и есть. Производство. Я каждый день делаю code review десятков а то и сотен строк кода. И если-бы не
механизмы FindBug, Cobertura, JUnit, Mockito я-бы просто потонул. Автоматизация проверки кода гарантирует
хотя-бы отсутствие ляпов и неоднозначностей подобно пост-инкрементам.

По поводу движения двух указателей в strcpy я не имею ничего против. Но при этом я оглядываюсь
на прото-ассемблерную семантику "C". Этот исходник написан в "духе" C и соответствует правильным
трендам.

В Java подобный код я не пропущу. Заверну на доработку.

в Java поведение подобного кода будет четко определено.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824220
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivв Java поведение подобного кода будет четко определено.И вы можете подтвердить своё высказывание ссылкой на JLS???
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824230
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Test.java
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
package test;

public class Test
{
  public static void main(String[] args)
  {
    int[] ar = {0, 0};
    int i = 0;
    
    ar[i++] = i++;
    System.out.println(i + ": " + ar[0] + ", " + ar[1]);
    
    ar[0] = ar[1] = i = 0;
    ar[++i] = ++i;
    System.out.println(i + ": " + ar[0] + ", " + ar[1]);
    
    ar[0] = ar[1] = i = 0;
    ar[i++] = ++i;
    System.out.println(i + ": " + ar[0] + ", " + ar[1]);
    
    ar[0] = ar[1] = i = 0;
    ar[++i] = i++;
    System.out.println(i + ": " + ar[0] + ", " + ar[1]);
  }
}

Хорошо, когда всего два компилятора и одна платформа:
Код: plaintext
1.
2.
3.
2: 1, 0
2: 0, 2
2: 2, 0
2: 0, 1
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824281
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
в тему забористой травы
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
package test;

public class Test
{
  public static void main(String[] args)
  {
    int[] ar = {0, 0};
    int i = 0;
    
    ar[++i] = ar[i] = ++i;
    System.out.println(i + ": " + ar[0] + ", " + ar[1]);
  }
}

Код: plaintext
2: 0, 2
Вообще не понимаю результат. Не понимаю, в частности, почему нет ArrayOutOfBoundException ...
Точнее, не понимаю почему при ассоциативности справа-налево, вычисления идут слева-направо.

P.S. Да, не совсем в тему, но всё-таки ...
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824300
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovТочнее, не понимаю почему при ассоциативности справа-налево, вычисления идут слева-направо.
Я уже выше писал - ассоциативность и приоритет влияют только на фазу синтаксического анализа.
А вычисления происходят позже и их порядок никакого отношения к этому не имеет.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824303
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyЯ уже выше писал - ассоциативность и приоритет влияют только на фазу синтаксического анализа.
А вычисления происходят позже и их порядок никакого отношения к этому не имеет.Вот это и составляет проблему.
Делая своё выпендрёжное выражение я полагался на правила приоритетов и ассоциативности. И считаю это вполне естественным.
Почему, внезапно, я должен делать отдельные поправки на отдельный порядок вычислений.

P.S. Не то, чтобы я был "реально недоволен", но хочется понять логику.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824305
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Конкретно в данном случае синтаксическое дерево выглядит так (если рассматривать только присвоения):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
(=  
  "ar[++i]" 
  (= 
    "ar[i]" 
    "++i"
  ) 
)


Вот интерпретатор обходит дерево вглубь и вычисляет аргументы каждого узла слева-направо.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824308
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovДелая своё выпендрёжное выражение я полагался на правила приоритетов и ассоциативности. И считаю это вполне естественным.
Не знаю. Я не считаю это естественным.
Вероятно у многих нечеткое описание приоритетов операций в некоторых книгах создает впечатление что речь про порядок вычислений. У меня такой иллюзии никогда не было. Но я и книг по программированию почти не читал :)
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824310
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyВот интерпретатор обходит дерево вглубь и вычисляет аргументы каждого узла слева-направо.
Кстати, этот порядок соответствует визуальному порядку этих операций в коде, поэтому именно его я вначале топика и предлагал зафиксировать при устранении UB в C++.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824311
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyКонкретно в данном случае синтаксическое дерево выглядит так (если рассматривать только присвоенияЯ готов согласится с вашим примером для "пользовательских" типов. Но только потому, что для пользовательских типов операторы подменяются на вызовы функций.
Встроенные операторы, собственно, для того и существуют, чтобы порядок их вычисления определялся правилами. В том числе - правилом ассоциативности.

P.S. Теперь я понимаю пример mayton, но каким надо быть садистом, чтобы пересталять некоммутирующие операции?...
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824312
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Операции тут не переставляются. Просто операнды вычисляются не в том порядке как вы думали :)
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824315
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyОперации тут не переставляются. Просто операнды вычисляются не в том порядке как вы думали :)Ну нельзя переставлять порядок вычислений для некоммутирующих операций. Нельзя.
Или пометить четким "неопределённое поведение" или следовать правилам. В том числе - правилу ассоциативности.
Ассоциативность права-налево - делаем вычисления справа-налево.
Хотим потенциальную оптимизацию для вычислений супротив ассоциативности? Вешаем табличку "неопределённое поведение".
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824321
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще раз. В последний.
"порядок вычислений для некоммутирующих операций" тут не менялся.
Операции вычисляются именно в порядке приоритетов.
Т.е. в конструкции a = b = c сначала вычисляется c, потом b, потом a - всегда.
Но поскольку a, b, c это в свою очередь тоже операции, то сами они вычисляются в произвольное удобное время (обычно - как только вычислены их соответствующие операнды).
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824323
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyТ.е. в конструкции a = b = c сначала вычисляется c, потом b, потом a - всегда.
Упс, я не это имел в виду.
Тут заменить на такую фразу:
Т.е. в конструкции a = b = c сначала вычисляется b = c, потом a = .. - всегда.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824326
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyТут заменить на такую фразу:
Т.е. в конструкции a = b = c сначала вычисляется b = c, потом a = .. - всегда.И что?
Как это меняет тот факт, что для встроенного правоассоциативного оператора ОП цепочка:
Код: sql
1.
a ОП b ОП c;

должна вычисляться не так, как разработчику компилятора удобно строить AST, а строго в порядке "c, затем b, затем a"?
Почему, указав:
Код: sql
1.
a * b / c;

я должен закладываться на то, что кому-то покажется оптимальней, типа эквивалентный, вариант:
Код: sql
1.
b / c * a

?
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824330
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Опять не поняли.
Ладно еще пример, совсем простой.

Код: plaintext
1.
a[1 + 2] = 3 + 4;


Вот в этом примере, я обязательно сначала должен вычислить 3+4?
Или я все-таки могу не нарушая логику выражения сначала вычислить 1 + 2, потом 3 + 4, а потом выполнить присвоение a[3] = 7?
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824331
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovskyсначала вычислить 1 + 2, потом 3 + 4, а потом выполнить присвоение a[3] = 7
Ну вот признайтесь честно, вы ведь когда мысленно выполняете это выражение, вы именно в таком порядке вычисляете?
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824338
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyНу вот признайтесь честно, вы ведь когда мысленно выполняете это выражение, вы именно в таком порядке вычисляете? Если нет других ограничений - да.
Но давайте рассмотрим "a * b / c".
Если сделать корявый, но простой парсер, то в стек префиксной машины может попасть сначала "* a, " и потом "/ b, c".
Извлекаем с вершины "/ b, c", cчитаем некий x, помещаем его в стек и теперь можно посчитать "* a, x".
Против школьной математики мы не погрешили.
Проблема в том, что на множестве дискретных и ограниченных целых чисел есть два эффекта, которых нет на сплошном и бесконечном множестве вещественных - переполнение и потеря точности.
В результате ассоциативность становится не просто "фигнёй из учебников по программированию", а существенным элементом языка.
На а то, что русскому естественно, арабу - ересь
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824340
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovЕсли сделать корявый, но простой парсер, то в стек префиксной машины может попасть сначала "* a, " и потом "/ b, c".
Ничего подобного в вашем примере с присвоениями не происходит.
Думаю завтра вы на свежую голову сами увидите это :)
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824341
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyНичего подобного в вашем примере с присвоениями не происходит.
Думаю завтра вы на свежую голову сами увидите это :)В моём примере порядок вычисления меняется с "ассоциативного" на "допустимый по правилу коммутативности":
Код: sql
1.
return (100 * 1 / 3) == (1 / 3 * 100)
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824343
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyНичего подобного в вашем примере с присвоениями не происходит.
Думаю завтра вы на свежую голову сами увидите это :)Упростим до:
Код: sql
1.
выр1 ОП выр2

В каком порядке считать выражения, являющиеся операндами оператора:
1. Как удобнее;
2. В соответствии с ассоциативностью оператора;
3. Слева-направо, т.к. именно в этом направлении двигаются глаза программиста.
Пункт первый - UB, но исключает нытьё после переопределения оператора.
Пункт второй понятен, но требует вспоминать эти самые правила ассоциативности. Напрягает прогрессивную общественность
Пункт третий тоже понятен. Американцам и русским. У арабов и евреев может быть другое мнение
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824408
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonid Kudryavtsev, Булгаков прекрасен, спасибо :)
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824555
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Топик почему-то вдохновил на повторное чтение замечательной статьи
http://www.interstron.ru/upload/images/pubs/Redkaya_professiya.pdf

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

Современный компиллятор С++ это в некотором роде... магия. И талант
людей его создающих.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824751
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Java. Пока проигрываем. Компиллятор не выдал предупреждений.

Код: java
1.
2.
3.
4.
5.
6.
 public static void main(String[] args){
        int[] v = {0, 0};
        int i = 0;
        v[i++] = i++;
        System.out.printf("%d %d",v[0],v[1]);
    }



1 0
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824782
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
FindBug тоже молчит.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824984
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

Предупреждений в джаве нет, т.к. поведение такого кода описано в спеках языка и этот код соответственно совершенно легальный.

То что вы не понимаете почему именно такой результат получается, не говорит о недостатке языка, а только о вашей недоработке в изучении языка :)
...
Рейтинг: 0 / 0
Порядок вычисления
    #38824991
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я уже писал что я думаю об автоматизации подобной проверки.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38825004
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

проверка не всегда возможна, и что более важно, далеко не всем она нужна :)

Там кто-то выше просил ссылку на спеку джавы
JLS, section 15.7 The Java programming language guarantees that the operands of operators appear to be evaluated in a specific evaluation order, namely, from left to right.
...
The left-hand operand of a binary operator appears to be fully evaluated before any part of the right-hand operand is evaluated.

Видите, никаких ссылок на ассоциативность и приоритет операций.

И это нормальное правило, которое следовало бы ввести в С/С++.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38825064
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovMasterZivв Java поведение подобного кода будет четко определено.И вы можете подтвердить своё высказывание ссылкой на JLS???

Да.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38825084
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Век живи, век учись - дураком помрёшь.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38825406
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Груви. Не уверен что 100% эквивалентный код. Пускай знающие поправят если чо.
Код: python
1.
2.
3.
4.
def v = [ 0 , 0 ]
def i = 0
v[i++] = i++;
println ""+v[0]+" "+v[1]



0 0
...
Рейтинг: 0 / 0
Порядок вычисления
    #38825431
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Scala. Почитал здесь http://www.scala-lang.org/files/archive/spec/2.11/

Похоже ... из коробки в ней нету пред- и пост- инкрементов.
...
Рейтинг: 0 / 0
Порядок вычисления
    #38825432
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть добавление единицы +=1
...
Рейтинг: 0 / 0
Порядок вычисления
    #38825458
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonScala. Почитал здесь http://www.scala-lang.org/files/archive/spec/2.11/

Похоже ... из коробки в ней нету пред- и пост- инкрементов.

Небольшая потеря.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Порядок вычисления
    #39267061
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Небольшой апдейт.

В стандарте С++17 будут изменены правила вычисления таких неоднозначных (по предыдущему стандарту) выражений:

1) Присвоение будет вычисляться всегда справа налево (сначала целиком то, что присваивается, потом то, куда присваивается).
2) Постфиксные выражения, такие как цепочки вызовов функций (func_a(a1, a2).func_b(b1, b2)) - всегда слева направо. Т.е. сначала вызывается первая функция, только потом вычисляются аргументы второй функции и т.д. Раньше порядок не был определен, и при интенсивной оптимизации это могло ломаться.
3) Операция << выполняется всегда слева направо (удивительно, но в старом стандарте вывод в поток через << это был UB, т.к. это аналог цепочки вызовов из п.2, просто случайно все работало, точнее не случайно, потому что компиляторы не дураки пишут )

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0145r2.pdf

Таким образом исходный пример:
Код: plaintext
1.
2.
3.
4.
std::vector<int> v = { 0, 0 };
int i = 0;
v[i++] = i++;
std::cout << v[0] << v[1] << endl;


в новом стандарте имеет строго определенный порядок вычислений, и дает результат
Код: plaintext
1.
2.
3.
4.
5.
// v[i++] = i++ 
int temp = i++; 
v[i++] = temp;
// v == { 0, 0 }
// i == 2
...
Рейтинг: 0 / 0
Порядок вычисления
    #39267167
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovskyи дает результат

// v == { 0, 0 }

Э?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Порядок вычисления
    #39267299
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovЭ?..
Если это вопрос, то он как-то нечетко сформулирован ))
...
Рейтинг: 0 / 0
Порядок вычисления
    #39267311
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyЕсли это вопрос, то он как-то нечетко сформулирован ))

Нет, это уже не вопрос.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Порядок вычисления
    #39270819
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovsky, какое у вас отношение к первому пункту? Если я не ошибаюсь, вы больше склонялись к другому варианту. Лично мне такой вариант нравится(из п.1), сейчас мне он кажется как минимум логичным. Кнут и другие алгористы для операции присваивания используют следующее обозначение: . Потому её можно (скорее нужно) понимать как вычисление значения b и запись результата в a. Но возможно я вновь что-то упускаю, или о чем-то не думаю. Но на первый взгляд, повторюсь, я считаю такое решение правильным и поддерживаю его
...
Рейтинг: 0 / 0
110 сообщений из 110, показаны все 5 страниц
Форумы / C++ [игнор отключен] [закрыт для гостей] / Порядок вычисления
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]