Как мы знаем, целочисленное переполнение со знаком — неопределенное поведение. Но есть кое-что интересное в C ++ 11 cstdint
документация:
целочисленный тип со знаком с шириной ровно 8, 16, 32 и 64 бита соответственно без битов заполнения и используя дополнение 2 для отрицательных значений (предоставляется только если реализация напрямую поддерживает тип)
И вот мой вопрос: так как стандарт прямо говорит, что для int8_t
, int16_t
, int32_t
а также int64_t
отрицательные числа являются дополнением 2, все еще ли переполнение этих типов неопределенным поведением?
редактировать Я проверил стандарты C ++ 11 и C11, и вот что я нашел:
C ++ 11, §18.4.1:
Заголовок определяет все функции, типы и макросы так же, как 7.20 в стандарте C.
C11, §7.20.1.1:
Имя определения типа
intN_t
обозначает целочисленный тип со знаком с шириной N, без дополнительных битов и представление дополнения до двух. Таким образом,int8_t
обозначает такой целочисленный тип со знаком шириной ровно 8 бит.
все еще переполнение этих типов неопределенным поведением?
Да. В соответствии с пунктом 5/4 стандарта C ++ 11 (в отношении любого выражения в целом):
Если во время оценки выражения результат не определен математически или не находится в диапазоне
представимые значения для его типа, поведение не определено. […]
Тот факт, что представление двойного дополнения используется для этих типов со знаком, не означает, что арифметика по модулю 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 неопределенное поведение
поведение, к которому настоящий международный стандарт не предъявляет никаких требований
[Примечание: при этом Международном
Стандарт опускает любое явное определение поведения или когда программа
использует ошибочную конструкцию или ошибочные данные. Допустимый неопределенный
поведение варьируется от полного игнорирования ситуации с
непредсказуемые результаты, ведущие себя во время перевода или программы
выполнение задокументированной характеристикой среды
(с выдачей диагностического сообщения или без него), до прекращения
перевод или исполнение (с выдачей диагностического
сообщение). Многие ошибочные программные конструкции не порождают неопределенных
поведение; они должны быть диагностированы .— конец примечание]