Арифметическое переполнение в C ++ 17 - PullRequest
0 голосов
/ 15 октября 2018
  1. Хорошо ли определено арифметическое переполнение для C ++ 17 для uint8_t, uint16_t, uint32_t, uint64_t?Если да, каково определенное поведение (выдержка из стандарта C ++ высоко ценится)
  2. Хорошо ли определено арифметическое переполнение для C ++ 17 для int8_t, int16_t, int32_t, int64_t?(выдержка из стандарта C ++ высоко ценится)
  3. Если какое-либо или все вышеперечисленное зависит от реализации, каковы определения для g ++ и clang?
  4. Если это специфично для архитектуры (как указывал Хавенард), мой вопрос относится к x86 (-64).
  5. Что если я сделаю меньшее беззнаковое целое - большее беззнаковое целое, оно четко определено?

Я видел первыйВ ответе на этот пост упоминается, что на мой вопрос # 1 он определен в стандарте C, хотя он не цитировал его, и я ничего не могу найти в стандарте C ++.

=================

Обновление 1:

убрано "недополнение" для каждого значения, так как это неправильный термин (спасибо @ach).Добавил # 5, чтобы выразить то, что я на самом деле имел в виду под "недостаточным количеством" (неправильно)

1 Ответ

0 голосов
/ 15 октября 2018

В надежде на создание канонического, вот некоторые нормативные спецификации (цитаты взяты из последнего черновика C ++):

  • Целые числа без знака не переполняются: см. 6.7.1:

Беззнаковые целые должны подчиняться законам арифметики по модулю 2n, где n - количество битов в представлении значения этого конкретного размера целого числа.(44) Это подразумевает, что арифметика без знака не переполняется, потому что результат, который не может быть представлен результирующим целочисленным типом без знака, уменьшается по модулю на число, которое на единицу больше наибольшего значения, которое может быть представлено результирующим целочисленным типом без знака.

  • Переполнение / недополнение со знаком целого не определено: см. 7.1.4:

Если во время вычисления выражения результат не определен математически илиза пределами представляемых значений для его типа поведение не определено.

Кстати, ни один из них не зависит от реализации, и компиляторы активно используют переполнения / недополнения для оптимизации.Например, как показано в следующем фрагменте:

void a();
void b();

void foo(int k) {
    int z = k+1;
    if (z < k) {
        a();
    } else {
        b();
    }
}

https://gcc.godbolt.org/z/0re-nM - ветвь исключается, даже если на реальной платформе из-за представления по модулю 2 z может фактически стать меньше, чемk.

...