Целочисленное переполнение не происходит: они перезапускаются с 0 - PullRequest
0 голосов
/ 28 февраля 2019

Я попробовал простой код и обнаружил, что целочисленные переменные не переполняются, вместо этого кажется, что последний компилятор C ++ представил новую функциональность, связанную с типами данных POD - если переменная пересекает свое максимальное значение, ее значения перезапускаются с 0:

#include <iostream>
#include <cstdint>
#include <stdexcept>

int main()
{
try
{
for (uint8_t idx = 254 ;  ; idx++)
{
std::cout << unsigned(idx) << std::endl;
}
}
catch(std::overflow_error e)
{
std::cout << "Error" << std::endl;
}
}

Когда я запускаю код, код исключения никогда не выполняется - но это желаемое поведение?

Ответы [ 4 ]

0 голосов
/ 28 февраля 2019

Это поведение для типов без знака в соответствии со стандартом:

Стандарт 6.7.1 / 4

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

Что вдохновляет сноску:

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

0 голосов
/ 28 февраля 2019

похоже, что последний компилятор C ++ представил новую функциональность

Нет.Так C ++ всегда указывался.

, если переменная пересекает свое максимальное значение, ее значения перезапускаются с 0

Если целое число без знака результат вычисления не может быть представлен типом, тогда вместо этого результатом будет представимое значение, которое соответствует математическому результату по модулю 2 n , где n - количество бит в представлении (т. е. конгруэнтноес наибольшим представимым значением + 1).

Другими словами, (наибольшее представимое целое число без знака + 1) равно 0, как вы заметили.

Обратите внимание, что это правило не применяется к знакуцелые числа.Переполнение целого числа со знаком приводит к неопределенному поведению.

PS Для базового типа не определена операция, генерирующая исключение.Большинство стандартных библиотечных функций тоже не выдают std::overflow_error.

0 голосов
/ 28 февраля 2019

unsigned int не переполняется и не переполняется, это основное различие между типами со знаком и без знака в C ++.unsigned типы ведут себя в соответствии с арифметикой по модулю (т. Е. Они «окружают») [basic.fundamental] / 4 .Если вы хотите вызвать целочисленное переполнение, используйте целочисленный тип со знаком.Но даже тогда целочисленное переполнение не вызывает исключение, а просто приводит к неопределенному поведению

0 голосов
/ 28 февраля 2019

Почти ничего не выбрасывает std::overflow_error;Переполнение беззнаковых значений уже определено в стандарте языка, чтобы обернуть его в 0, это не считается «исключительным» случаем, поэтому исключение никогда не будет выброшено для простой целочисленной математики без знака.За cppreference docs на целочисленное арифметическое переполнение :

Целочисленная арифметика без знака всегда выполняется по модулю 2 n , где n - количество битов в данном конкретномцелое число.Например, для unsigned int добавление одного к UINT_MAX дает ​0, а вычитание одного из ​0 дает UINT_MAX.

Аналогично, стандартные библиотечные модули редко используют его :

Единственными стандартными библиотечными компонентами, которые выдают это исключение, являются std::bitset::to_ulong и std::bitset::to_ullong.

Математические функции компонентов стандартной библиотеки не выдают это исключение (математические функции сообщают об ошибках переполнения, как указано в math_errhandling).Сторонние библиотеки, однако, используют это.Например, boost.math бросает std::overflow_error, если boost::math::policies::throw_on_error включено (настройка по умолчанию).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...