vak: (Default)
[personal profile] vak
Сложить два целых числа, вернуть целое. Породить исключение в случае арифметического переполнения.
int add(int a, int b);
Удивительно, сколько народу обламывается на этой задачке.

Date: 2020-08-02 15:09 (UTC)
juan_gandhi: (Default)
From: [personal profile] juan_gandhi

Достаточно проверить равенство знаков, и пробовать сложить абсолютные величины.

Date: 2020-08-02 15:48 (UTC)
waqur: (Default)
From: [personal profile] waqur
А как с точки зрения стандарта (C/C++), переполнение знаковых целых — определено? Насколько я помню, для беззнаковых с определённостью переполнений всё было норм, а для знаковых что-то там было нечисто.

Я в курсе, что в процессоре инструкция add одна для всех типов операндов (и знаковых, и беззнаковых, и их комбинаций), я интересуюсь исключительно в контексте того, не съедет ли компилятор с катушек и не вставит ли туда инструкцию ud2, не выбросит ли весь код как недостижимый и т.д.

Date: 2020-08-02 15:55 (UTC)
juan_gandhi: (Default)
From: [personal profile] juan_gandhi

Нет смысла спрашивать меня про стандарт. Я его не знаю (да и не знал никогда).

Date: 2020-08-02 18:48 (UTC)
archaicos: Шарж (Default)
From: [personal profile] archaicos
Компилятор не со зла что-то делает. Логика такая:
1. undefined behavior не определено никак
2. компилятор не обязан его детектировать (и во многих ситуациях принципиально не может это сделать во время компиляции)
3. компилятор его не детектирует, а просто считает, что его не происходит, что программист не ошибся
4. в данном конкретном случае компилятор посчитает, что переполнения не произойдёт (а если произойдёт, то это undefined behavior же, ну и хер с ним)
5. это ему может открыть пути для оптимизации, т.е. здесь он может выкинуть код, следующий за оператором сложения, который проверяет на переполнение (которого ведь не возникает, а если возникает, то это UB и проблема программиста-недоучки, а не компилятора)

Date: 2020-08-02 22:38 (UTC)
waqur: (Default)
From: [personal profile] waqur
в данном конкретном случае компилятор посчитает, что переполнения не произойдёт (а если произойдёт, то это undefined behavior же, ну и хер с ним)

это очень оптимистичный взгляд на вещи: UB => ну и хер с ним

компиляторы обычно думают по-другому: UB => код можно выкинуть

ярчайший пример для целочисленного переполнения:
https://news.ycombinator.com/item?id=11147068

поначалу у народа от таких фокусов была истерика:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=30475

а потом ничё, привыкли

Date: 2020-08-02 23:10 (UTC)
archaicos: Шарж (Default)
From: [personal profile] archaicos
Вы не поняли сути. Компилятор не выискивает UB, и найдя, решает покуражиться просто заради прикола.

Нет. Компилятор смотрит на вещи так, как-будто UB не происходит. Т.е., например, он видит выражение "a + 1 > a" как 1, если a - signed int. И если такое выражение влияет на логику оптимизатора (потому, например, что оно является условием if или тернарного условия), то какой-то код может быть и выкинут. Но могут быть и более тонкие последствия. Например, из-за того, что то выражение равно 1, компилятор может счесть, что диапазон значений какого-то другого выражения (или переменной) может быть ограничен интересным образом, что в свою очередь может иные оптимизации разрешить.

Date: 2020-08-03 08:08 (UTC)
waqur: (Default)
From: [personal profile] waqur
Как-то была история с LLVM, касающаяся бесконечных циклов с пустым телом. С точки зрения стандарта C++, такие циклы — это UB, так что llvm их просто выбрасывал. Когда разработчики Rust наткнулись на это — была та ещё драма. Вопрос решался пустой ассемблерной вставкой с volatile-аттрибутом, IIRC.

Date: 2020-08-03 15:50 (UTC)
archaicos: Шарж (Default)
From: [personal profile] archaicos
Опять же, не «UB, а значит можно выкинуть», а у кода пустого бесконечного цикла нет никаких т.н. side effects (доступа к volatile-переменным, модификации объекта или файла, вызова функции, которая может сделать одно или более из перечисленного, и т.д. – по стандарту), и значит, что цикл можно выкинуть.
В стандарт просто не внесли зависание как побочный эффект (вероятно, забыли, хотя зуб не даю, т.к. очевидно, бесконечные циклы в ходу издревле). Ну и вот, бесконечный цикл пал жертвой оптимизации в какой-то момент.

Date: 2020-08-03 07:53 (UTC)
lomeo: (Default)
From: [personal profile] lomeo
> поначалу у народа от таких фокусов была истерика:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=30475

OMG, that's hilarious!