关于字节数组到长长(64位)数组与长(32位)的问题

时间:2010-01-11 23:22:49

标签: c++

我有一个具有十六进制值的字节数组,我最初将这些值放在unsigned long中。 我目前正在通过Ubuntu使用32位处理器。但是,我可能不得不将此程序移植到64位处理器。

现在我知道strtoul功能但是因为我能够转换它会通过直接分配任何问题我没有打扰该功能。我把它放在unsigned long中的原因是因为我在考虑小/大端的问题,因此使用像signed long这样的寄存器只会处理这个问题而不管处理器。但是,我一直在考虑我的程序如何在64位处理器上运行。

由于我使用的是32位处理器,它可能只识别32位长,而64位处理器仅识别64位长,这会使我签名的长阵列处于危险之中。所以,为了解决这个问题,我把这个签名的数组做成了很长的时间。这会解决我的担忧吗?还是我需要做别的事?

一些帮助和解释将不胜感激。我的所有代码都是用c ++编写的。

3 个答案:

答案 0 :(得分:2)

除了使用longlong long之外,你应该使用类似uint32_t之类的typedef,或类似的东西,所以它在所有平台上都可以是32位,除非这不是什么你想要吗?

但是,如果您只是在执行以下操作,那么看起来您确实存在字节序的潜在问题:

char bytes[4] = {0x12, 0x23, 0xff, 0xed};
long* p_long = reinterpret_cast<long*>(bytes);

std::cout << std::hex << *p_long << std::endl; // prints edff2312 on a little endian platform, 1223ffed on a big endian one.

因为解释为整数时字节的实际值将根据字节顺序而改变。转换结尾here有一个很好的答案。

答案 1 :(得分:1)

您可能希望查看SO 2032744以获取big-endian与little-endian问题的示例。

我不确定使用寄存器是什么意思会解决您的字符串问题。我们需要看到要知道的代码。但是,如果需要在不同计算机之间通过线路传输整数值,则需要确保正确处理大小和字节顺序。这意味着两端必须就如何处理它达成一致 - 即使他们实际上做的事情不同。

在英特尔平台上将字节数组复制为“long”会因在SPARC平台上将同一阵列复制到“long”而产生不同的结果。要通过寄存器,您必须使用类似于以下的代码:

void        st_uint4(Uint4 l, char *s)
{
    s += sizeof(Uint4) - 1;
    *s-- = l & 0xFF;
    l >>= 8;
    *s-- = l & 0xFF;
    l >>= 8;
    *s-- = l & 0xFF;
    l >>= 8;
    *s   = l & 0xFF;
}

Uint4   ld_uint4(const char *s)
{
    int i;
    Uint4   j = 0;

    for (i = 0; i < 4; i++)
    {
        j = (j << 8) | (*s++ & 0xFF);
    }
    return(j);
}

有多种方法可以编写该代码。


发表评论:

在跨机器处理数据时,您必须非常小心。显示的两个函数是彼此的反转。 'ld_uint4()'函数接受一个字节数组并将其加载到一个4字节有符号整数中(假设你有一个Uint4的typedef映射到一个4字节有符号整数 - 来自inttypes.h或stdint.h的uint32_t是一个好赌注)。 st_uint4()函数执行相反的操作。此代码使用大端存储格式(MSB在字节数组中是第一个),但在两种类型的平台上使用相同的代码(两者都没有性能优势 - 并且没有条件编译,这可能更重要)。您可以编写代码以使用little-endian存储;你可以编写代码,这样一种机器对另一种机器的惩罚就会减少。

了解磁盘上的数据布局至关重要 - 仔细定义它们并以平台中立的方式也是至关重要的。处理(单字节代码集)字符串很容易;处理宽字符串(UTF-16或UTF-32)就像处理整数一样 - 如果你愿意,你可以使用类似于Uint2和Uint8的代码的代码(例如,我预先打包了这些函数 - 我只是复制了Uint4版本;我也有SintN函数 - 对于复制内容,差异并不重要,但对于内存比较,有符号和无符号值的比较技术是不同的。)

处理float和double仍然比较棘手 - 尽管如果你能安全地假设IEEE 754格式,它主要是你面临的一个大端和小端问题(那可能是一些与工会的混淆)。我使用的代码库依赖于双/浮动平台(令人讨厌,但是可以追溯到IEEE 754之前的日子无处不在)所以我没有平台中立代码。同时注意对齐;英特尔芯片允许未对齐访问,但其他芯片(SPARC,PowerPC)不会,或产生大量开销。这意味着如果你复制一个4字节的值,如果你做一个简单的复制,源和目标地址必须是4字节对齐;上面的存储/加载函数没有那个问题,可以处理任意对齐。再次,要警惕过度优化(过早优化)。

答案 2 :(得分:1)

1)Signed vs Unsigned不会让你对endian问题免疫。唯一的数据类型字节序不可知是一个字节(char)。如果你有两台不同的机器,还需要交换endian所需的一切

2)64位机器将始终为您提供某种类型的32位整数,您可以使用它从数组中提取值。所以这不应该是一个问题,只要你确定两台机器都使用32位int(并且你可能编码数据的字节顺序)。