Почему знаковое переполнение это UB?

Почему знаковое переполнение это UB, ведь с C++20 всегда используется 2's complement, а значит результат однозначно определен?


Ответы (3 шт):

Автор решения: Qwertiy

Потому что оптимизация.

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

→ Ссылка
Автор решения: Pavel Mayorov

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

x > y + 2
x - 2 > y

Математика нам говорит, что эти формулы эквивалентны. Но если разрешить знаковое переполнение - они эквивалентными быть перестанут!

→ Ссылка
Автор решения: wololo

До C++20 стандарт языка допускал три способа для представления знаковых целых чисел:

  • Signed magnitude
  • Ones' complement
  • Two’s complement

Начиная с C++20 для представления целых чисел может использоваться только two’s complement. Автором этого изменения является некто Jean François Bastien (e-mail: [email protected]). Предлагаемые изменения в конкретных пунктах стандарта языка, мотивацию и обсуждения изменений вы можете найти в документе P0907R4.

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

This paper proposes the following:
...

  • Status-quo If a signed operation would naturally produce a value that is not within the range of the result type, the behavior is undefined. The author had hoped to make this well-defined as wrapping (the operations produce the same value bits as for the corresponding unsigned type), but WG21 had strong resistance against this.

Основные возражения комитета таковы:

  • Проблемы производительности. Оптимизатор не сможет предполагать, что переполнение никогда не происходит, и выполнять оптимизации, вытекающие из этого предположения.
  • Возникают сложности при реализации таких штук как санитайзеры.
  • Google считает, что 90% всех переполнений является багом, поэтому модулярная арифметика для знаковых целых не нужна.

Вопрос на stackoverflow.com с примерами оптимизаций, когда оптимизатор считает, что переполнения при знаковой арифметике не возможны: Is there some meaningful statistical data to justify keeping signed integer arithmetic overflow undefined?

→ Ссылка