strtoul не является безопасным с порядком байтов?

Итак, я делаю преобразование из строки в unsigned long, используя strtoul как на машинах с прямым порядком байтов, так и с прямым порядком байтов. Машина с прямым порядком байтов возвращает правильное значение, а машина с прямым порядком байтов — нет. Действительно ли эта функция несовместима с машинами с обратным порядком байтов? Если да, то есть ли обходной путь?

Код:

printf ("%s\n",cLongs);
theLongs[i] = strtoul(cLongs, NULL, 10);
cout << "returned unsigned long value from string: " << theLongs[i] << endl;

Результат с прямым порядком байтов:

1099188638048931
returned unsigned long value from string: 1099188638048931

Результат с большим порядком байтов:

1099188638048931
returned unsigned long value from string: 4294967295

P.S. Похоже, что в примере с обратным порядком байтов всегда возвращается одно и то же число.


person Jeff Schmitz    schedule 22.04.2011    source источник


Ответы (1)


strtoul возвращает ULONG_MAX при переполнении. Это то, что вы бьете. Я предполагаю, что один работает на 32-битном, а другой на 64-битном, помимо различий Endianess. 4294967295 == 0xFFFFFFFF, что для 32-битной машины будет ULONG_MAX.


Попробуйте, работает ли следующее для вас в обеих системах. Пока я мог протестировать его только на 64-битном Linux с обратным порядком байтов. Если это так, вы можете использовать строковые потоки для преобразования (что в любом случае является стилем С++ для выполнения задач):

#include <iostream>
#include <sstream>

int main()
{
  using namespace std;
  string sval("1099188638048931"); // your huge value, exceeding 32bit
  istringstream sst(sval); // assign string to a stream
  unsigned long long myval;
  sst >> myval; // convert stream to unsigned 64bit integer
  cout << myval << endl; // output the converted result
  return 0;
}

Обратите внимание, что unsigned long long должно быть unsigned __int64 с MSVC. Другие компиляторы могут иметь другие имена. Если вам повезет, у вас будут стандартные типы на всех ваших платформах, и вы сможете использовать uint64_t . ..

person 0xC0000022L    schedule 22.04.2011
comment
Это кажется правильным ответом после попытки меньшего числа без знака. Есть ли способ обойти эту проблему или я застрял между молотом и наковальней? - person Jeff Schmitz; 22.04.2011
comment
@Jeff: Я почти уверен, что нет кроссплатформенного решения, потому что это выходит за рамки стандарта C. Но вместо среды выполнения C вы можете использовать строковый поток C++ и оператор << для получения большего целочисленного значения. Я почти уверен, что С++ должен быть к этому готов. Я посмотрю, смогу ли я собрать вам небольшой пример, взломанный вместе. Также даст ответ, готов C++ или нет :) - person 0xC0000022L; 22.04.2011
comment
@Jeff: посмотрите, есть ли в ваших системах strtoull (strtouq в BSD), который использует unsigned long long - вероятно, 64-битный на обоих. - person Tony Delroy; 22.04.2011
comment
@STATUS_ACCESS_DENIED и @TONY: Спасибо за помощь, unsigned long long, кажется, работает, но мне нужно посмотреть, будет ли он работать для моего приложения. Я занимаюсь сетевым проектом, и эти неподписанные длинные сообщения представляют собой зашифрованные части сообщений с использованием Blowfish. Я собираюсь посмотреть, смогу ли я заставить этот алгоритм работать с unsigned long long. Если бы я использовал unsigned long на 64-битном конце и unsigned long long на 32-битном конце, будет ли битовый сдвиг работать правильно? (конечно, имея в виду проблемы с порядком байтов) - person Jeff Schmitz; 22.04.2011
comment
@Jeff: не могли бы вы сообщить нам, работает ли он у вас с образцом кода? - person 0xC0000022L; 22.04.2011
comment
@STATUS: кажется, что и strtoull, и строковый поток отлично работают, чтобы преобразовать строку в unsigned long long, в настоящее время я работаю над проблемой, описанной в комментарии выше. - person Jeff Schmitz; 22.04.2011
comment
@Jeff: что касается этого вопроса: да, сдвиг битов должен работать. Но обычно Blowfish воспринимает данные как двоичные данные. Таким образом, предполагая, что переданное (строковое) значение возникло на машине BE, зашифрованное сообщение в форме 64-битного целого числа на машине LE не имело бы смысла для алгоритма. Вам может быть безопаснее с простым массивом байтов здесь ... но я не знаю всех фактов, поэтому просто догадываюсь в некоторой степени. - person 0xC0000022L; 22.04.2011