Целочисленное переполнение и неопределенное поведение

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

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

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

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

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

Итак, почему кто-то должен избегать причинения этого? Я что-то пропустил?

4 ответа

Решение

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

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

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

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 не так просты, они много гадают и оптимизируются.

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

Другие вопросы по тегам