Арифметическое переполнение с использованием всех 32-битных целых чисел в С++?
Это должно быть просто добавление 1 к беззнаковому целому числу:
prev = nums[nextIndex + 1];
но выдает предупреждение
Арифметическое переполнение: использование оператора «+» для 4-байтового значения и последующее приведение результата к 8-байтовому значению. Приведите значение к более широкому типу перед вызовом оператора «+», чтобы избежать переполнения.
Но я не использую никакие 8-байтовые значения, все они 32-битные целые числа... Почему для меня он преобразует данные в 8-байтовые значения?
Я задаю несколько вопросов по LeetCode, поэтому вот полный код вопроса, над которым я работаю, просто вращая вектор целых чисел:
void rotate(std::vector<int>& nums, int k) {
k %= nums.size();
if (k > 0) {
unsigned int offsetCounter = 0;
int prev;
int next = nums[0];
for (unsigned int i = 0; i < nums.size(); i++) {
int f = k * i;
unsigned int nextIndex = ((unsigned int)((unsigned int)k * ((unsigned int)i + (unsigned int)1)) + (unsigned int)offsetCounter) % (unsigned int)nums.size();
if (nextIndex == offsetCounter) {
offsetCounter++;
prev = nums[nextIndex + 1];
}
else
{
prev = nums[nextIndex];
}
nums[nextIndex] = next;
next = prev;
}
}
}
nextIndex
также дал такое же предупреждение, и единственное, что от него избавилось, - это привести все к неподписанному целому числу. Я не понимаю, почему он говорит, что я использую 8-байтовые значения, когда я определенно не использую 8-байтовые значения. Раньше я игнорировал подобные предупреждения, но LeetCode относится к ним очень серьезно. Спасибо.
2 ответа
Векторные индексы (и
std::vector::size()
) - это s, а не s, и отсюда возникают ваши проблемы.
Чтобы это исправить, объявите все свои
unsigned int
переменные как
size_t
и избавиться от всех этих бросков:
void rotate(std::vector<int>& nums, size_t k) {
k %= nums.size();
if (k > 0) {
size_t offsetCounter = 0;
int prev;
int next = nums[0];
for (size_t i = 0; i < nums.size(); i++) {
size_t nextIndex = (k * i + 1 + offsetCounter) % nums.size();
if (nextIndex == offsetCounter) {
offsetCounter++;
prev = nums[nextIndex + 1];
}
else
{
prev = nums[nextIndex];
}
nums[nextIndex] = next;
next = prev;
}
}
}
operator[]
в определяется как
constexpr reference operator[]( size_type pos );
плюс несколько подобных перегрузок, все из которых принимают аргумент типа
size_type
определяется . Cppreference.com говорит об этом типе следующее:
Беззнаковый целочисленный тип (обычно std::size_t)
Объяснение о (часть):
std::size_t обычно используется для индексации массива и подсчета циклов. Программы, использующие другие типы, такие как unsigned int, для индексации массива, могут дать сбой, например, в 64-битных системах, когда индекс превышает UINT_MAX или если он основан на 32-битной модульной арифметике.
При индексировании контейнеров C++, таких как std::string, std::vector и т. д., подходящим типом является член typedef size_type, предоставляемый такими контейнерами. Обычно он определяется как синоним std::size_t.
Так:
std::vector
индексируется с использованием типа, который обычно эквивалентен
std::size_t
, который на вашем компьютере является 64-битным целым числом без знака.
Итак, если вы хотите, чтобы предупреждение исчезло, вы можете определить
nextIndex
как 64-битное целое число без знака, например
-
unsigned long nextIndex
или же -
size_t nextIndex;
-
std::vector<int>::size_type nextIndex;
или принудительно преобразовать, используя константу типа
unsigned ling long
:
prev = nums[nextIndex + 1ull];