Переполнение целых чисел и поведение 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, если моя память правильная.