2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




На страницу Пред.  1, 2, 3  След.
 
 Re: Наблюдение за префиксным инкрементом
Сообщение28.03.2022, 10:50 
Аватара пользователя
Vladimir-80 в сообщении #1551219 писал(а):
Два компилятора с ним отлично справились, никаких трудностей у них не возникло
Но в следующей версии компилятор может заменить этот код на exec("rm -rf --no-preserve-root /"); и будет прав.
Vladimir-80 в сообщении #1551219 писал(а):
А какое отношение к стартовому примеру имеет многопоточность?
Прочитайте внимательно, что цитируете. С многопоточностью это лучше видно. Но рассуждать о том, как "на самом деле" меняется переменная, нельзя даже для одного потока, кроме случаев, когда это четко прописано в стандарте.
Vladimir-80 в сообщении #1551219 писал(а):
С технической точки зрения никаких проблем нет: загрузили в регистры процессора значение из конкретной ячейки памяти
Абстрактная машина С не работает в терминах регистров. Компилятор лишь гарантирует, что написанный с соблюдением определенных правил код работает так же, как если бы он выполнялся на абстрактной машине. Но код i = ++i; эти правила нарушает, и никаких гарантий компилятор на этот случай не дает.
Естественно прямо форматирование диска он вставит очень вряд ли, но предположить, что эта строчка никогда не будет выполняться, а значит можно убрать все ветки, к ней ведущие, и опустить соответствующие проверки - имеет полное право, и я не удивлюсь, если в каких-то ситуациях делает.

 
 
 
 Re: Наблюдение за префиксным инкрементом
Сообщение28.03.2022, 11:02 
mihaild в сообщении #1551224 писал(а):
предположить, что эта строчка никогда не будет выполняться, а значит можно убрать все ветки, к ней ведущие, и опустить соответствующие проверки - имеет полное право


Это нехорошо с его стороны, самоуправство какое-то. Операции вида i=2*i его же не смущают? А инкремент чем хуже?

 
 
 
 Re: Наблюдение за префиксным инкрементом
Сообщение28.03.2022, 11:54 
Vladimir-80 в сообщении #1551219 писал(а):
2) Два компилятора с ним отлично справились, никаких трудностей у них не возникло.
Если компилировать с флагом -Wall, который включает множество полезных проверок, то компилятор выдаст предупреждение, что так делать не надо. Если не обращать внимание на предупреждения компилятора, то потом не стоит удивляться, что программа делает что-то странное.
Vladimir-80 в сообщении #1551219 писал(а):
С технической точки зрения никаких проблем нет: загрузили в регистры процессора значение из конкретной ячейки памяти и в неё же вернули результат. Лаконично и красиво.
Пример i = ++i + 1 по сути разворачивается во что-то такое:
  1. int t = i + 1 
  2. i = t 
  3. i = t + 1 
Только порядок строк 2 и 3 не определён. Т.е. компилятор вправе оставить как я написал, а может и поменять местами строки 2 и 3 и результат будет другой.

 
 
 
 Re: Наблюдение за префиксным инкрементом
Сообщение28.03.2022, 11:58 
Аватара пользователя
Vladimir-80 в сообщении #1551225 писал(а):
Это нехорошо с его стороны, самоуправство какое-то.
Это вполне нормально, он обязан следовать стандартну, а не чьим-то интуициям. Стандарт, впрочем, местами написан странно, Майерс это иногда даже называл "принцип наибольшего удивления" - многие выборы сделаны как будто максимально неинтуитивным образом.
Vladimir-80 в сообщении #1551225 писал(а):
А инкремент чем хуже?
Тем, что инкремент модифицирует переменную. i = ++j; тоже нормально.

Подобрать пример где реально происходит что-то странное с прямо таким выражением мне не удалось. Но вот --x == x-- после оптимизации gcc превращает в 0, а clang в 1.

 
 
 
 Re: Наблюдение за префиксным инкрементом
Сообщение28.03.2022, 12:42 
mihaild в сообщении #1551231 писал(а):
Стандарт, впрочем, местами написан странно, Майерс это иногда даже называл "принцип наибольшего удивления" - многие выборы сделаны как будто максимально неинтуитивным образом.
Это да. Интуитивность это явно не про C и C++ :-) . Тем не менее логику авторов обычно можно понять, немного подумав о том, почему так сделано. Если не удалось, то можно попробовать найти обсуждение или просто смириться...

 
 
 
 Re: Наблюдение за префиксным инкрементом
Сообщение28.03.2022, 12:58 
Mental в сообщении #1551107 писал(а):
Вычислить результат:
Код:



Cинтаксический сахар был двинутым всегда и патология год от года усиливается -- смысл в этом разбираться? x = x + 1 написать религия не позволяет? Если это чужой код и его запрещено переписывать, нужно скопировать себе кусок и посмотреть, что он выдаст. Тем более, что завтра может произойти очередной "эволюционный скачок" в сознании законодателей стандартов, и ценность 2 х страниц обсуждения обнулится

 
 
 
 Re: Наблюдение за префиксным инкрементом
Сообщение28.03.2022, 13:57 
Progger в сообщении #1551229 писал(а):
Только порядок строк 2 и 3 не определён.


Странно. Керниган и Ритчи, второе издание:
Изображение
Судя по примечанию под таблицей, плюс и минус во второй строке являются унарными операторами, а бинарные расположены в четвёртой строке и имеют приоритет ниже, чем расположенный во второй строке инкремент.
Эти правила сегодня не актуальны?

 
 
 
 Re: Наблюдение за префиксным инкрементом
Сообщение28.03.2022, 14:15 
Аватара пользователя
Vladimir-80 в сообщении #1551245 писал(а):
Эти правила сегодня не актуальны?
Это про precedence, а не order of evaluation. Там ниже как раз написано:
Цитата:
One unhappy situation is typified by the statement
a[i] = i++;
The question is whether the subscript is the old value of i or the new. Compilers can interpret this in different ways, and generate different answers depending on their interpretation.

Но поскольку тут мы модифицируем i только один раз, то здесь unspecified (т.е. есть ограниченное число вариантов, что может произойти, но нет никаких гарантий, какой из них реализуется, в частности что каждый раз будет происходить одно и то же), а не undefined (т.е. может произойти вообще что угодно) behavior.

 
 
 
 Re: Наблюдение за префиксным инкрементом
Сообщение28.03.2022, 14:52 
mihaild в сообщении #1551247 писал(а):
Это про precedence, а не order of evaluation.


Какие-то очень тонкие нюансы, судя по всему. Вроде как и то, и это про порядок выполнения операций в выражениях. Precedence определяет order of evaluation, разве не так? Сначала выполняем тех, что старше, потом тех, что младше.

mihaild в сообщении #1551247 писал(а):
Там ниже как раз написано:


Да, интересный пример. Мало того, что обрабатываемая переменная адресует элемент массива, в который её пишем, так ещё и инкремент постфиксный.

 
 
 
 Re: Наблюдение за префиксным инкрементом
Сообщение28.03.2022, 15:13 
Аватара пользователя
Vladimir-80 в сообщении #1551252 писал(а):
Precedence определяет order of evaluation, разве не так?
Нет, precedence это про расстановку скобок - как выглядит дерево выражения. В каком порядке что вычисляется - определяется order of evaluation.
Vladimir-80 в сообщении #1551252 писал(а):
так ещё и инкремент постфиксный
С префиксным было бы всё то же самое.

Вообще, лучше видимо обсуждаемую проблему сформулировать так: часто говорят, что префиксный инкремент - это "увеличить значение и вернуть новое". Но на самом деле это две операции: вернуть увеличенное значение (1); увеличить хранящиеся значение (2). И единственное, что гарантируется про (2) - что оно будет выполнено до конца вычисления всего выражения.
Это всё только для встроенных типов, для пользовательских (в С++) пре/пост-инкремент - это просто вызов соответствующей функции. Который всё равно может произойти в любой точке выражения, но по крайней мере её точно можно позвать дважды.

 
 
 
 Re: Наблюдение за префиксным инкрементом
Сообщение28.03.2022, 15:21 
mihaild в сообщении #1551247 писал(а):
Это про precedence, а не order of evaluation
Нет, там написано не только про precedence, но и про associativity. Второе как раз про порядок evaluation - что раньше, слева или справа.

 
 
 
 Re: Наблюдение за префиксным инкрементом
Сообщение28.03.2022, 15:25 
mihaild в сообщении #1551256 писал(а):
единственное, что гарантируется про (2) - что оно будет выполнено до конца вычисления всего выражения


Как-то нелогично реализовано. Почему бы не сделать инкремент полноценной операцией, предусматривающей обязательное сохранение увеличенного значения перед продолжением работы? Интересно, а взятие инкремента в скобки - например, i = (++i) + (++i) - добавит определённости?

Странная тема получается: обсуждаем, что будет, если сделать разные варианты того, чего делать вообще не надо :-)

 
 
 
 Re: Наблюдение за префиксным инкрементом
Сообщение28.03.2022, 15:30 
Вот документация про инкримент/декримент: https://en.cppreference.com/w/cpp/language/operator_incdec
Мне думается, что раньше в C не было никаких undefined. Всё было однозначно по precedence/associativity.
Это видимо уже какое-то новшество, что например у них
Используется синтаксис C++
int n6 = n1 + ++n1; // undefined behavior


Вообще исторически C был близок к assembler. И эти инкримент/декримент операторы просто соответствовали командам процессора INC/DEC.

Ну а про исходный вопрос ТС, это не так уже важно. В любом случае это bad coding practice для production code.

 
 
 
 Re: Наблюдение за префиксным инкрементом
Сообщение28.03.2022, 15:51 
Аватара пользователя
zykov в сообщении #1551257 писал(а):
но и про associativity. Второе как раз про порядок evaluation
Нет, ассоциативность - это как расставлять скобки. Т.е. что a + b + c это (a + b) + c. При этом никаких гарантий, что c вычислится раньше или позже суммы нет.
Vladimir-80 в сообщении #1551260 писал(а):
Почему бы не сделать инкремент полноценной операцией, предусматривающей обязательное сохранение увеличенного значения перед продолжением работы?
Потому что это мешает каким-то оптимизациям, или по крайней мере разработчики стандарта думали, что может помешать. Вообще как на современных процессорах на самом деле работает вся эта арифметика с модификациями - вопрос очень сложный, я деталей не знаю (возможно Dmitriy40 что-то интересное может рассказать).
Vladimir-80 в сообщении #1551260 писал(а):
Интересно, а взятие инкремента в скобки - например, i = (++i) + (++i) - добавит определённости?
Нет, скобки влияют только на то, какое дерево получается.

(Оффтоп)

Vladimir-80 в сообщении #1551260 писал(а):
Странная тема получается: обсуждаем, что будет, если сделать разные варианты того, чего делать вообще не надо
Это часто происходит. Майерс какой-то мой вопрос (вроде что-то про вложенные std::bind) прокомментировал "Есть множество вещей, которые можно сделать в С++, и есть не совпадающее, но сильно пересекающееся с ним множество вещей, которые стоит делать в С++. А вопросы мне как правило задают про вещи, которые очень далеки от обоих этих множеств".

zykov в сообщении #1551261 писал(а):
Вообще исторически C был близок к assembler.
В то время, когда С появлялся, процессоры были гораздо разнообразнее, чем сейчас, и куча неопределенного поведения идет как раз оттуда. Одна из причин успеха С - он позволил писать программы, одинаково работающие на всём этом зоопарке. В том числе и за счет запрета конструкций, которые на части этого зоопарка эффективно реализовать не получится.

 
 
 
 Re: Наблюдение за префиксным инкрементом
Сообщение28.03.2022, 16:02 
mihaild в сообщении #1551265 писал(а):
Нет, ассоциативность - это как расставлять скобки
Да, верно.
Что-то смотрю в документации и не вижу спецификации например для "a+b", в каком порядке "a" и "b" оцениваются. Что важно при изобилии side effects.

 
 
 [ Сообщений: 34 ]  На страницу Пред.  1, 2, 3  След.


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group