我的问题是如何将一个UINT32值转换为一个UINT8数组[4](使用C/C++),最好不依赖于字节序的方式?此外,如何从UINT8数组[4]重构UINT32值,以便回到起点?
我的问题是如何将一个UINT32值转换为一个UINT8数组[4](使用C/C++),最好不依赖于字节序的方式?此外,如何从UINT8数组[4]重构UINT32值,以便回到起点?
你并没有明确说明通过独立于字节序实现什么 - 因为字节数组必须具有某种字节序,所以这是不清楚的。即便如此,以下其中之一必定能够满足您的要求:
给定UINT32 v
和UINT8 a[4]
:
(使用计算机的本机字节序):
UINT8 *vp = (UINT8 *)&v;
a[0] = vp[0];
a[1] = vp[1];
a[2] = vp[2];
a[3] = vp[3];
或者:
memcpy(a, &v, sizeof(v));
或者:
*(UINT32 *)a = v;
(又称为“网络序”):
a[0] = v >> 24;
a[1] = v >> 16;
a[2] = v >> 8;
a[3] = v;
a[0] = v;
a[1] = v >> 8;
a[2] = v >> 16;
a[3] = v >> 24;
*(UINT32 *)a = v;
是一个非常危险的假设 - 如果a
没有初始化对齐到UINT32
字边界,这很可能会导致未对齐访问错误。 - Tom Carpenter例如,像这样:
UINT32 value;
UINT8 result[4];
result[0] = (value & 0x000000ff);
result[1] = (value & 0x0000ff00) >> 8;
result[2] = (value & 0x00ff0000) >> 16;
result[3] = (value & 0xff000000) >> 24;
编辑:添加括号(>> 的优先级似乎高于&)
>> 0
),而且必须是一个非常糟糕的编译器才不能将它们优化掉。 - Oliver Charlesworth&
运算符在美学上有多少价值,事实是它们会导致代码难以理解。>>
的优先级高于&
。 - TonyKuint8
的事实,所以所有掩码都是不必要的,正如@Stephen指出的那样。 - Oliver Charlesworth也可以使用指针来完成。 (这是小端序,但如果您使用相同的重构方法,它不会有影响)
uint32 in = 0x12345678;
uint8 out[4];
*(uint32*)&out = in;
uint8 in[4] = {0x78, 0x56, 0x34, 0x12};
uint32 out;
out = *(uint32*)&in
*(uint32*)&out = in;
是一个非常危险的假设 - 如果a
没有初始化对齐到uint32
字边界,这可能会导致某些处理器上的未对齐访问错误。 - Tom Carpenter使用由一个包含4个uint8类型的数组和一个uint32类型组成的联合体。
这样它就会自动按照c语言内在指针魔法进行排序(数组是指向数组开头的指针)。