19

我想知道将字节数组转换为短/整数/长时系统字节序是否重要。如果代码在 big-endian 和 little-endian 机器上运行,这样做会不正确吗?

short s = (b[0] << 8) | (b[1]);
int i = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3])
4

5 回答 5

24

是的,字节顺序很重要。在 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_sntoh_l将有关字节序的决定卸载到socket知道这些事情的操作系统实现。请注意,默认网络顺序是大端(nin ntoh_x),因此将字节数组数据作为大端将是最直接的方法。

正如 OP (@Mike) 所指出的,boost它还提供字节顺序转换功能。

于 2012-12-03T06:28:29.093 回答
4
// 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)
于 2016-03-14T14:14:39.520 回答
1

您可以为此使用联合。字节顺序很重要,要更改它,您可以使用大多数 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;
}
于 2016-09-03T11:25:23.643 回答
0

不,就字节顺序而言这很好,但如果你int的 s 只有 16 位宽,你可能会遇到问题。

于 2012-12-03T06:25:22.637 回答
0

您指定的问题,即您使用现有字节数组的位置,将在所有机器上正常工作。你最终会得到相同的答案。

但是,根据您创建该流的方式,它可能会受到字节序的影响,并且您最终可能不会得到您认为的数字。

于 2012-12-03T06:59:44.593 回答