【发布时间】:2017-12-11 12:26:34
【问题描述】:
好的,所以我正在构建一个 Base64 编码器/解码器,可以将十六进制转换为 base64 并返回,但我发现了一个我正在尝试理解的奇怪问题,代码如下:
string b64_encode(string str)
{
string newStr = "";
string ref = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
unsigned long long h = 0;
for(int i=0; i<str.size(); i+=3)
{
//Get every 3 chars
char a = str[i];
char b = str[i+1];
char c = str[i+2];
//Now, convert each hex character (base 16) to it's equivalent decimal number
//and merge them into one variable
h = strtoull(&a, nullptr, 16) << 8; //shift left by 8 bits
h |= strtoull(&b, nullptr, 16) << 4; //shift left by 4 bits
h |= strtoull(&c, nullptr, 16); //no shift required only the first 2 characters need
cout << h << endl; //for testing purposes only
}
return newStr;
}
当我在 Mac OSX 上运行此代码时,我得到以下结果,这是不正确的:
4052
3959
1570
4091
3814
...
但是,我在 Windows 8 的 Visual Studio 2013 上编写了相同的代码,它给了我正确的值:
1170
1901
518
2921
1734
...
我使用的十六进制字符串:
string str = "49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d";
所以我的问题是,有没有办法在 Mac OSX 上也显示正确的数字?我在网上查了一下,但没有太大帮助。
【问题讨论】:
-
&a不是以 0 结尾的字符串,因此您会调用未定义的行为。 -
@mch 如果是这样的话,它在 Windows 上是如何工作的?
-
似乎与mac字节序有关
-
您可以修复未定义的行为,因此它不再靠运气起作用:ideone.com/LxmwW3 或您的示例输入:ideone.com/2GMMJX
-
@MegaColorBoy 就我个人而言,我不会使用 strtoull 将单个十六进制数字转换为数字。我会使用
(ch > '9' ? ( 10 + (ch - 'a')) : (ch - '0'))之类的东西,假设我知道输入已被检查。