关于字节数组到长长(64位)数组与长(32位)的问题
我有一个有十六进制值的字节数组,我最初把这些值放在一个无符号长整型中。 我现在通过Ubuntu使用32位处理器。但是,我可能必须将此程序移植到64位处理器。关于字节数组到长长(64位)数组与长(32位)的问题
现在我知道strtoul函数,但因为我能够转换它会通过直接任务的任何问题,我没有打扰与该功能。我之所以把它放在一个没有签名的long中是因为我在考虑小/大的endian问题,所以使用像signed long这样的寄存器只会为我处理这个问题,而不管处理器如何。但是现在我一直在想我的程序如何在64位处理器上工作。
因为我在32位处理器,它可能只认识32位长VS 64位处理器只能识别64位长,这使我的签署多头排列处于危险之中。所以,为了解决这个问题,我只是把这个签名数组做了很长时间。这会解决我的担忧吗?还是我需要做别的事情?
一些帮助和解释将不胜感激。我的所有代码都在C++中。
而不是使用long
或long 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有一个很好的答案。
你可能想看看SO 2032744作为一个大端到小端问题的例子。
我不确定你使用寄存器意味着什么,可以解决你的endian-ness问题。我们需要查看代码才能知道。但是,如果您需要通过不同机器之间的线路传输整数值,则需要确保正确处理大小和字节顺序。这意味着两端必须就如何处理它达成一致 - 即使他们实际上以不同的方式做事。
复制的字节数组成Intel平台上的“长”将从复制同一阵列成“长”在SPARC平台上产生不同的结果。要通过注册,您必须使用类似于以下代码:
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字节的有符号整数 - uint32_t来自inttypes.h或stdint.h是好打赌)。 st_uint4()函数执行反向操作。此代码使用big-endian存储格式(MSB在字节数组中首先使用),但在两种类型的平台上都使用相同的代码(没有性能优势 - 也没有条件编译,这可能更重要)。你可以编写代码来使用little-endian存储;你可以编写代码,以便在一种类型的机器上比其他类型的机器更少受到惩罚。
了解磁盘上的数据布局至关重要 - 仔细定义并以平台中立的方式进行定义也至关重要。处理(单字节代码集)字符串很简单;处理宽字符字符串(UTF-16或UTF-32)就像处理整数一样 - 如果你愿意,你可以使用与上面的代码类似的代码(例如,我已经预先打包了这样的函数 - 我只是复制Uint4版本;我也有SintN函数 - 对于复制的东西,差异并不重要,但对于内存比较,signed和unsigned值的比较技术是不同的)。
处理float和double更棘手 - 尽管如果你可以安全地假设IEEE 754格式,它主要是你面对的一个大端到小端的问题(也许是一些工会的狡猾问题)。我使用的代码库与叶/双浮动平台相关(这是一个令人讨厌的问题,但是可以追溯到IEEE 754之前的日子无处不在),所以我没有平台中立的代码。也要小心路线;英特尔芯片允许未对齐访问,但其他芯片(SPARC,PowerPC)不支持,或产生大量开销。这意味着,如果您复制一个4字节的值,则如果您执行简单复制,则源地址和目标地址必须为4字节对齐;上面的存储/加载函数没有这个问题,可以处理任意的对齐。再次警惕过度优化(过早优化)。
乔纳森,因为我还是比较新的所有这一切我想我只是在运行32位的ubuntu 9.1中编译一个程序,其中长为4字节,然后将其移植到64位的太阳站。因此,我目前所了解的是,不仅64位的长度会变大而且不同,而且读取的方式也会颠倒,使得数值不同。所以,如果我使用ld_unit4函数你有他们会它扭转数组中的十六进制值?对于我来说,我从来没有真正做过任何点点算术。谢谢。 – djones2010 2010-01-12 17:04:08
1)签名与未签名不会让你免受endian问题的影响。唯一的数据类型endian不可知是一个字节(char)。如果你有两台不同的机器,用其他所有的东西你需要交换endian
2)一个64位的机器总是会为你提供某种类型的32位整数,你可以使用它来将值从你的数组中拉出来。所以这不应该是一个问题,只要你确定两台机器都使用32位int(并且你可能编码数据的字节顺序)。
我实际上在做以下操作 字节输出[somesize]; memset(output,0x00,somesize); memset 我用散列值填充它,然后做一个直接分配的循环。 很长很长的另一个输出[somesize]; 运行for循环并执行任务。 现在你说这仍然是一个永恒的问题? 我会看看你发给我的是什么。 – djones2010 2010-01-11 23:40:27
是的,我不完全确定你在说什么,但我认为是。 (你可以编辑问题添加一些代码来演示你在做什么?) – James 2010-01-12 00:01:53
我可以使用int64_t bswap_64(int64_t x)。我可以得到一个例子,我可以如何使用这个与十六进制值的字节数组? – djones2010 2010-01-12 16:59:37