Переполнение целых чисел и поведение undefined

Есть много вопросов об обнаружении целочисленного переполнения перед фактическим добавлением/вычитанием из-за возможного undefined behavior. Итак, мой вопрос:

Почему он будет производить этот undefined behavior в первую очередь?

Я могу думать о 2 причинах:

1) Процессор, который генерирует исключение в этом случае. Конечно, он может быть отключен, и, скорее всего, это хорошо написанный CRT сделает это.

2) Процессор, который использует другие двоичные представления чисел (1 дополнение? base 10?). В этом случае поведение undefined будет проявляться как отличный результат (но не будет сбой!). Ну, мы могли бы жить с этим.

Итак, почему кто-то избегает его? Я что-то пропустил?

Ответы

Ответ 1

Хотя большинство современных процессоров используют 2 дополнения, а целочисленное переполнение приводит к предсказуемому модулю обхода, это отнюдь не универсально - чтобы поддерживать язык достаточно общим, чтобы его можно было использовать в самом широком диапазоне архитектур, лучше указать, что целое число переполнение - UB.

Ответ 2

В то время как историческая причина, связанная с переполнением, была указана как поведение undefined, вероятно, было этим ложным устаревшим представлением (одним дополнением/знаковой величиной) и прерываниями переполнения, современной причиной для его сохранения undefined является оптимизация. Как намекнул J-16 SDiZ, тот факт, что подписанное переполнение - это поведение undefined, позволяет компилятору оптимизировать некоторые условия, чья алгебраическая истина (но не обязательно истинность на уровне представления) уже установлена ​​предыдущей ветвью. Это может также позволить компилятору алгебраически упростить некоторые выражения (особенно те, которые связаны с умножением или делением) способами, которые могут дать разные результаты, чем первоначально написанный порядок оценки, если подвыражение содержит переполнение, поскольку компилятору разрешено предположить, что переполнение не происходит с операндами, которые вы ему дали.

Другим огромным примером поведения undefined с целью разрешения оптимизации являются правила псевдонимов.

Ответ 3

Биты undefined behavior в спецификации включают некоторую оптимизацию компилятора. Например:

if (a > 0 && b > 0) {
    if ( a + b <= 0 ) {
       // this branch may be optimized out by compiler
    } else {
       // this branch will always run
    }
}

Современные компиляторы C не так просты, они много угадывают и оптимизируют.

Ответ 4

Я думаю, что ваше предположение 1), что это может быть отключено для любого данного процессора, было ложным по крайней мере в одной важной исторической архитектуре, CDC, если моя память правильная.