Числовые ограничения и переполнение
Запрашивайте std::numeric_limits и изучайте правила переполнения знаковых и беззнаковых типов.
«Числовые ограничения и переполнение» — бесплатный урок C++ Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C++ Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C++ Academy содержит 4 уроков всего.
Почему важны ограничения типов
У каждого числового типа есть максимальное и минимальное представимое значение. Их превышение может незаметно привести к неправильным результатам или неопределённому поведению.
std::numeric_limits
Получить ограничения любого числового типа можно с помощью заголовочного файла <limits>. Это константы времени компиляции, поэтому дополнительных затрат во время выполнения нет.
#include <limits>
std::cout << std::numeric_limits<int>::max() << "\n";
std::cout << std::numeric_limits<int>::min() << "\n";
std::cout << std::numeric_limits<double>::epsilon();Распространённые запросы
Наиболее полезные члены:
max()— наибольшее значениеmin()— наименьшее положительное значениеlowest()— наиболее отрицательное значениеepsilon()— наименьшая значимая разница (для чисел с плавающей точкой)digits10— гарантированное количество десятичных цифр
Переполнение знакового целого числа
Переполнение знакового целого числа — это неопределённое поведение. Компилятор может предполагать, что оно никогда не происходит, и выполнять неожиданные оптимизации.
int x = std::numeric_limits<int>::max();
x += 1; // UB — anything can happenЗацикливание беззнакового целого числа
Переполнение беззнакового типа определено: значения зацикливаются по модулю 2^N. Иногда это полезно, но часто становится источником ошибок.
unsigned int u = 0;
u -= 1; // wraps to 4,294,967,295 (UINT_MAX)Переполнение и потеря точности чисел с плавающей точкой
При переполнении числа с плавающей точкой превращаются в inf, а не приводят к аварийному завершению. При потере точности результатом становятся субнормальные числа или 0.
double x = 1e308;
x *= 100;
std::cout << x; // infБезопасное обнаружение переполнения
Для знаковых целых чисел проверяйте возможность переполнения до выполнения операции. Компиляторы предоставляют встроенные средства проверяемой арифметики, например __builtin_add_overflow в GCC/Clang.
if (a > std::numeric_limits<int>::max() - b) {
// overflow would happen
}
int sum = a + b;C++20: std::ssize и std::cmp_less
В C++20 в <utility> появились безопасные вспомогательные функции для сравнения целых чисел: std::cmp_equal, cmp_less, cmp_greater. Они корректно обрабатывают смешивание знаковых и беззнаковых типов.
Неявные преобразования таят опасность
Смешивание знаковых и беззнаковых типов при сравнении незаметно преобразует знаковый операнд в беззнаковый — это частый источник трудно обнаруживаемых ошибок.
int a = -1;
unsigned int b = 1;
if (a < b) std::cout << "yes";
else std::cout << "no"; // prints "no"!Проверки во время компиляции
Используйте static_assert, чтобы проверять предположения о размерах при написании переносимого кода.
static_assert(sizeof(int) >= 4, "Need at least 32-bit int");Средства санитизации помогают при тестировании
Соберите программу с -fsanitize=undefined, чтобы обнаруживать переполнение знаковых чисел во время выполнения при тестировании.
g++ -fsanitize=undefined -O1 main.cppБыстрая проверка
Что происходит при переполнении сложения знакового целого числа в C++?
Итоги
Используйте std::numeric_limits, чтобы получать границы типов. Переполнение знаковых чисел не определено, а беззнаковые значения зацикливаются. Смешивайте знаковые и беззнаковые типы с большой осторожностью. Санитайзеры и безопасные сравнения C++20 помогают защитить код.
Часто задаваемые вопросы
Урок «Числовые ограничения и переполнение» бесплатный?
Да — полный текст урока «Числовые ограничения и переполнение» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C++ Academy, подпишись на CoddyKit PRO. Курс C++ Academy содержит 4 уроков всего.
Чему я научусь в уроке «Числовые ограничения и переполнение»?
Запрашивайте std::numeric_limits и изучайте правила переполнения знаковых и беззнаковых типов. Ты практикуешь C++ Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C++ Academy?
Предыдущий опыт не требуется. C++ Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Числовые ограничения и переполнение»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C++ Academy?
Да. Каждый урок C++ Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Целочисленные типы и типы с плавающей точкой
- Заголовок cmath: pow, sqrt, abs, round
- Случайные числа с заголовком random
- Числовые ограничения и переполнение