Преобразование строки в шестнадцатеричный код ошибки: 'std::out_of_range'

avatar
Packa
8 августа 2021 в 22:15
130
1
2

У меня есть очень простая программа, которая преобразует шестнадцатеричную строку в целочисленное значение. Код выглядит нормально, но выдает ошибку времени выполнения:

.

вызывается завершение после создания экземпляра 'std::out_of_range' что(): стои

Вот код, в котором возникает ошибка:

int dump[4];
string hexCodes[4] = {"fffc0000", "ff0cd044", "ff0000fc", "ff000000"};
for (int i = 0; i < 4; i++)
{
    dump[i] = 0;
    dump[i] = stoi(hexCodes[i], 0, 16);
    cout << dump[i] << endl;
}

Я попытался прочитать пару страниц, таких как эта. Я до сих пор не могу найти ничего, что относится к моей проблеме. Что я делаю неправильно, что вызывает эту ошибку?

Источник
Sam Varshavchik
8 августа 2021 в 22:21
0

0xff000000 равно 4278190080. Наибольшее значение, которое может быть сохранено в 32-битном целом числе, равно 2147483647. Если преобразовать это значение в шестнадцатеричное, причина станет очевидной.

Spencer
8 августа 2021 в 22:26
0

@SamVarshavchik 32-битные шестнадцатеричные значения со старшим набором битов соответствуют отрицательным целым числам. Вы должны опубликовать ответ, объясняющий, почему stoi не преобразует строку, начинающуюся с 8 до f, в отрицательное целое число.

Remy Lebeau
8 августа 2021 в 22:44
0

@Spencer "32-битные шестнадцатеричные значения с установленным старшим битом соответствуют отрицательным целым числам" - только когда шестнадцатеричный код представляет со знаком целое число. Вместо этого он может представлять беззнаковое целое число. Рассматриваемый код предполагает подписанный, но его можно легко настроить для поддержки беззнакового.

Spencer
8 августа 2021 в 22:53
1

В конце концов, @RemyLebeau stoi возвращает целое число со знаком. Даже если его можно настроить, мы не знаем, интересует ли OP подписанный или неподписанный, и в этом случае вместо этого следует использовать stoul. Поэтому на этот вопрос требуется разъяснение от Packa или, по крайней мере, ответ, который охватывает оба случая.

Nate Eldredge
9 августа 2021 в 01:23
0

Packa: Какой результат вы ожидали получить? 4294705152, или -262144, или что-то еще?

Packa
9 августа 2021 в 02:03
0

@NateEldredge 4294705152 был ожидаемым результатом. Все остальные индексы положительные, а не отрицательные.

Ответы (1)

avatar
Nate Eldredge
9 августа 2021 в 03:29
1

stoi выдаст out_of_range, если значение не находится в диапазоне, который может представлять int. Число 0xfffc0000 (4294705152) не входит в этот диапазон для 32-битного int, так как оно больше 2^31-1 (2147483647). Таким образом, создание исключения — это именно то, что он должен делать.

unsigned будет работать, но stou отсутствует, поэтому используйте stoul. Затем вы, вероятно, захотите использовать unsigned dump[4], так как вы знаете, что значение может быть представлено unsigned int. (Опять же, если в вашей системе они 32-битные. uint32_t может быть безопаснее.) В качестве бонуса это гарантирует, что cout << dump[i] выводит 4294705152 по желанию.

(Если вы переключитесь на stoul, но сохраните dump как массив int, значение будет преобразовано в int путем присваивания. В C++20 и для большинства распространенных систем в более ранних версиях Стандарты C++, преобразование будет "зациклено" на -262144, а вывод dump[i] с << выведет его именно таким образом, как целое число со знаком минус. вы хотите.)