Я хотел определить гигабайт в своем коде, поэтому я использовал, во-первых, unsigned long
, Тем не мение, unsigned long
не мог справиться 2 * gigabyte
,
Итак, я заменил его на long long
но я получил ту же ошибку компиляции / предупреждение:
ошибка: целочисленное переполнение в выражении [-Werror = переполнение]
Наконец, я посмотрел на большие целые числа и обнаружил, что мне нужно uintmax_t, так как он 128 бит.
К сожалению, я все еще получаю ту же ошибку. Я предполагаю, что есть небольшая ошибка, но я мог найти это.
Пожалуйста, найдите ниже соответствующий код:
#define kilobyte 1024
#define megabyte 1024 * kilobyte
#define gigabyte 1024 * megabyte
uintmax_t threshold = 2 * gigabyte;
Наконец, после запуска ‘make’
g++ -Wall -Wextra -Werror -pedantic -pthread -std=c++0x -g -o lcr main.cpp
Я получил:
main.cpp: In function ‘int main(int, char**)’:
main.cpp:104:17: error: integer overflow in expression [-Werror=overflow]
cc1plus: all warnings being treated as errors
Давайте посмотрим на кусок кода:
uintmax_t x = 2 * 1024;
Что здесь происходит, у нас есть (int) 2 * (int) 1024
, а затем мы продвигаем результат uintmax_t
,
Вместо этого мы хотим: (uintmax_t) 2 * (uintmax_t) 1024
, Мы можем легко продвигать целые числа в long long
с помощью этого метода:
#define kilobyte 1024ULL
#define megabyte 1024ULL * kilobyte
#define gigabyte 1024ULL * megabyte
uintmax_t threshold = 2ULL * gigabyte;
Произведение двух int
с явно еще типа int
— и литералы, с которыми мы имеем дело в ваших макросах, имеют тип int
,
10243 = 230 почти представимо в 32-битной int
, Тем не мение, 2 * 230 = 231 точно один слишком большой для 32-разрядного подписанного int
держать.
Это может быть решено путем определения констант как объектов соответствующего типа:
const std::uintmax_t kilobyte = 1024;
const std::uintmax_t megabyte = 1024 * kilobyte;
const std::uintmax_t gigabyte = 1024 * megabyte;
const std::uintmax_t threshold = 2 * gigabyte;
Благодаря обычным арифметическим преобразованиям, выполняемым над операндами *
переполнение не может произойти.