strtoul函数在大端和小端模式下是否安全?

4

我正在进行一个将字符串转换为无符号长整型的操作,使用的是在小端和大端机器上都可以使用的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

顺便说一句,对于大端示例,似乎总是返回相同的数字。

1个回答

4

strtoul函数在溢出时返回ULONG_MAX。这就是你遇到的问题。我假设一个运行在32位系统上,另一个运行在64位系统上,加上字节序的差异。4294967295 == 0xFFFFFFFF,对于32位机器来说,它将是ULONG_MAX


请尝试在两个系统上测试以下代码是否有效。我只能在64位小端Linux上进行测试。如果有效,您可以使用字符串流进行转换(这也是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;
}

请注意,使用MSVC编译器时,unsigned long long必须改为unsigned __int64。其他编译器可能有其他名称。如果你很幸运,在所有平台上都有标准类型,那么可以使用uint64_t...

尝试使用较小的无符号整数后,这似乎是正确答案。是否有办法解决这个问题,还是我陷入了一个进退维谷的境地? - Jeff Schmitz
@Jeff:我很确定没有跨平台的解决方案,因为这超出了C标准。但是,你可以使用C++字符串流和<<运算符来获取更大的整数值,而不是使用C运行时。我相信C++应该已经为此做好了准备。我会尝试编写一个小例子给你看看。同时也会回答C++是否做好了准备 :) - 0xC0000022L
@Jeff:查看一下你的系统是否具有strtoull(在BSD上为strtouq),它使用unsigned long long,在两个系统上可能都是64位的。 - Tony Delroy
@STATUS_ACCESS_DENIED和@TONY:感谢您的帮助,unsigned long long似乎可以工作,但我需要看看它是否适用于我的应用程序。我正在进行一个网络项目,这些unsigned longs是使用blowfish加密消息的一部分。我将尝试看看能否让该算法与unsigned long long一起工作。如果我在64位端使用unsigned long,在32位端使用unsigned long long,那么位移操作是否能正常工作呢?(当然要注意字节序问题) - Jeff Schmitz
@状态:strtoull和字符串流似乎都可以很好地将字符串转换为unsigned long long,我目前正在解决上面评论中描述的问题。 - Jeff Schmitz
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接