Это знаковое целочисленное переполнение по-прежнему неопределенное поведение в C++?


как мы знаем, переполнение целого числа со знаком является неопределенным поведением. Но есть кое-что интересное в C++11 cstdint документы:

знаковый целочисленный тип с шириной ровно 8, 16, 32 и 64 бит соответственно не бит обивка и использование дополнения 2 для отрицательных значений (при условии, что реализация непосредственно поддерживает тип)

ссылка

и вот мой вопрос: поскольку стандарт явно говорит, что для int8_t,int16_t,int32_t и int64_t отрицательные числа являются дополнением 2, по-прежнему переполнение этих типов является неопределенным поведением?

Edit я проверил стандарты C++11 и C11 и вот что я нашел:

C++11, §18.4.1:

заголовок определяет все функции, типы и макросы так же, как 7.20 в стандарте C.

C11, §7.20.1.1:

имя typedef intN_t обозначает знаковый целочисленный тип с шириной N, без битов заполнения и представлением дополнения двух. Таким образом,int8_t обозначает такой знаковый целочисленный тип с шириной ровно 8 бит.

3 57

3 ответа:

по-прежнему переполнение этих типов является неопределенным поведением?

да. в соответствии с пунктом 5/4 стандарта C++11 (в отношении любого выражения в целом):

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

тот факт, что представление дополнения two используется для этих типах не означает, что арифметика по модулю 2^n используется при вычислении выражений любого из этих типов.

о без подписи арифметика, с другой стороны, стандарт явно указывает, что (пункт 3.9.1/4):

целые числа без знака, объявленные unsigned,должны подчиняться законам арифметики по модулю 2^n где n-число битов в представлении значения этого конкретного размера целое число

это означает, что результат арифметической операции без знака всегда "математически определено", и результат всегда находится в пределах представимого диапазона; поэтому 5/4 не применяется. Сноска 46 объясняет это:

46) это означает, что без подписи арифметика не переполняется, потому что результат, который не может быть представлен результирующим беззнаковый целочисленный тип уменьшается по модулю числа, которое равно единице больше, чем наибольшее значение, которое может быть представлено результирующий целочисленный тип без знака.

только потому, что тип определен для использования представления дополнения 2s, он не следует за тем, что арифметическое переполнение в этом типе становится определенным.

неопределенное поведение арифметического переполнения со знаком используется для оптимизации; например, компилятор может предположить, что если a > b затем a + 1 > b также; это не выполняется в беззнаковой арифметике, где вторая проверка должна быть выполнена из-за возможности того, что a + 1 может обернуться к 0. Кроме того, некоторые платформы могут генерировать сигнал ловушки при арифметическом переполнении (см., например,http://www.gnu.org/software/libc/manual/html_node/Program-Error-Signals.html); стандарт продолжает допускать это.

Я бы так и сделал.

из стандартной документации (ПГ.4 и 5):

1.3.24 неопределенное поведение

поведение, к которому данный международный стандарт не предъявляет никаких требований

[ Примечание: неопределенное поведение можно ожидать, когда этот международный Стандарт не содержит четкого определения поведения или использует ошибочную конструкцию или ошибочные данные. Допустимо не определено диапазоны поведения от полного игнорирования ситуации с непредсказуемые результаты, чтобы вести себя во время перевода или программы выполнение в документированном виде, характерном для окружающей среды (с выдачей диагностического сообщения или без нее), к завершению перевода или исполнения (с выдачей диагностического сообщение.) Многие ошибочные программные конструкции не порождают неопределенных поведения; они должны быть диагностированы.-- конец Примечание]