strtoul не является endian безопасным? - PullRequest
4 голосов
/ 22 апреля 2011

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

Код:

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

Little endian результат:

1099188638048931
returned unsigned long value from string: 1099188638048931

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

1099188638048931
returned unsigned long value from string: 4294967295

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

1 Ответ

4 голосов
/ 22 апреля 2011

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


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

#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 ...

...