我想知道将字节数组转换为短/整数/长时系统字节序是否重要。如果代码在 big-endian 和 little-endian 机器上运行,这样做会不正确吗?
short s = (b[0] << 8) | (b[1]);
int i = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3])
我想知道将字节数组转换为短/整数/长时系统字节序是否重要。如果代码在 big-endian 和 little-endian 机器上运行,这样做会不正确吗?
short s = (b[0] << 8) | (b[1]);
int i = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3])
是的,字节顺序很重要。在 little endian 中,最重要的字节位于 short 或 int 的上半部分 - 即 short 的位 8-15 和 int 的位 24-31。对于大端,字节顺序需要颠倒:
short s = ((b[1] << 8) | b[0]);
int i = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0]);
请注意,这假定字节数组是小端顺序。字节数组和整数类型之间的字节序和转换不仅取决于 CPU 的字节序,还取决于字节数组数据的字节序。
建议将这些转换包装在可以知道(通过编译标志或在运行时)系统字节序并正确执行转换的函数中。
此外,为字节数组数据创建一个标准(例如,总是大端),然后使用socket
ntoh_s
和ntoh_l
将有关字节序的决定卸载到socket
知道这些事情的操作系统实现。请注意,默认网络顺序是大端(n
in ntoh_x
),因此将字节数组数据作为大端将是最直接的方法。
正如 OP (@Mike) 所指出的,boost
它还提供字节顺序转换功能。
// on little endian:
unsigned char c[] = { 1, 0 }; // "one" in little endian order { LSB, MSB }
int a = (c[1] << 8) | c[0]; // a = 1
//------------------------------------------------ ----------------------------
// on big endian:
unsigned char c[] = { 0, 1 }; // "one" in big endian order { MSB, LSB }
int a = (c[0] << 8) | c[1]; // a = 1
//------------------------------------------------ ----------------------------
// on little endian:
unsigned char c[] = { 0, 1 }; // "one" in big endian order { MSB, LSB }
int a = (c[0] << 8) | c[1]; // a = 1 (reverse byte order)
//------------------------------------------------ ----------------------------
// on big endian:
unsigned char c[] = { 1, 0 }; // "one" in little endian order { LSB, MSB }
int a = (c[1] << 8) | c[0]; // a = 1 (reverse byte order)
您可以为此使用联合。字节顺序很重要,要更改它,您可以使用大多数 c 编译器作为内在函数提供的 x86 BSWAP 指令(或其他平台的类似指令)。
#include <stdio.h>
typedef union{
unsigned char bytes[8];
unsigned short int words[4];
unsigned int dwords[2];
unsigned long long int qword;
} test;
int main(){
printf("%d %d %d %d %d\n", sizeof(char), sizeof(short), sizeof(int), sizeof(long), sizeof(long long));
test t;
t.qword=0x0001020304050607u;
printf("%02hhX|%02hhX|%02hhX|%02hhX|%02hhX|%02hhX|%02hhX|%02hhX\n",t.bytes[0],t.bytes[1] ,t.bytes[2],t.bytes[3],t.bytes[4],t.bytes[5],t.bytes[6],t.bytes[7]);
printf("%04hX|%04hX|%04hX|%04hX\n" ,t.words[0] ,t.words[1] ,t.words[2] ,t.words[3]);
printf("%08lX|%08lX\n" ,t.dwords[0] ,t.dwords[1]);
printf("%016qX\n" ,t.qword);
return 0;
}
不,就字节顺序而言这很好,但如果你int
的 s 只有 16 位宽,你可能会遇到问题。
您指定的问题,即您使用现有字节数组的位置,将在所有机器上正常工作。你最终会得到相同的答案。
但是,根据您创建该流的方式,它可能会受到字节序的影响,并且您最终可能不会得到您认为的数字。