整数到字节数组Little Endian,反之亦然

时间:2014-03-24 09:26:51

标签: c bit-manipulation

我希望方法将整数转换为字节数组(小端), 从字节数组(以小端方式编码)到C中的整数; 无论我们是在LE还是BE机器上工作。

这些功能对此有用吗?

void Int2ByteArrayLE(int x,unsigned char *byteArray)
{

  byteArray[0]=x;
  byteArray[1]=x>>8;
  byteArray[2]=x>>16;
  byteArray[3]=x>>24;
}


void ByteArrayLE2Int(unsigned char *byteArray, int*x)
{
  *x=byteArray[0] | (byteArray[1]<<8) | (byteArray[2]<<16) | (byteArray[3]<<24);
}

PS。如果x已签名,这是否也有效?

4 个答案:

答案 0 :(得分:2)

您实际要做的是在主机字节顺序和网络字节顺序之间进行转换。您需要的是函数htonlntohl

要从主机转换为网络字节顺序,请使用:

uint32_t n = (uint32_t)htonl((uint32_t)h);

反方向:

int h = (int)ntohl((uint32_t)n);

这些函数了解主机平台的字节顺序。因此,如果您在大端机器上执行代码,这些函数什么都不做。但是在一个小端机器上,函数会反转字节。

在评论中,您认为您的通信协议要求以小端字节顺序传递信息。这肯定是个错误。您应该遵循标准协议并以网络字节顺序在线路上传输数据。

如果你真的无法改变协议,并且希望通过线路获得小端,那么你只需要一个memcpy。你的价值观已经是小端,并明显扭转了不会有帮助的字节。

如果您发现自己处于大端客户端,那么您现在需要反转字节。使用此功能:

uint32_t reverseBytes32(uint32_t v){
  return ((v & 0xFF) << 24) | ((v & 0xFF00) << 8) 
         | ((v & 0xFF0000) >> 8) | ((v & 0xFF000000) >> 24);
}

您需要使用强制转换功能将已签名的int重新解释为未签名的uint32_t

答案 1 :(得分:1)

您的代码存在一些问题:

  • 在16位int的系统上,代码无效。
  • 在99%的情况下,在有符号整数上使用按位运算符并没有任何意义。如果有符号整数包含负数,如果你左移,你甚至会遇到未定义的行为。

因此代码通常是不可移植的。您需要将代码更改为以下内容:

#include <stdint.h>

void uint32_to_ByteArrayLE (uint32_t x, uint8_t* byteArray)
{
  // explicit casts will prevent implicit conversion warnings:
  byteArray[0] = (uint8_t)(x >>  0);
  byteArray[1] = (uint8_t)(x >>  8);
  byteArray[2] = (uint8_t)(x >> 16);
  byteArray[3] = (uint8_t)(x >> 24);
}


void ByteArrayLE_to_uint32 (const uint8_t* byteArray, uint32_t* x)
{
  /* casts -before- shifting are necessary to prevent integer promotion 
     and to make the code portable no matter integer size: */

  *x = (uint32_t)byteArray[0] <<  0 | 
       (uint32_t)byteArray[1] <<  8 | 
       (uint32_t)byteArray[2] << 16 | 
       (uint32_t)byteArray[3] << 24;
}

如果不是第二个函数中的强制转换,则转移将发生在int上,这不是您想要的。

答案 2 :(得分:0)

让我们看一下标准(5.8 Shift运算符):

“E1&lt;&lt; E2 ......如果E1具有有符号类型和非负值,并且E1 * 2 ^ E2在结果类型中可表示,那么这就是结果值;否则,行为是未定义“。

“E1的值&gt;&gt; E2 s E1右移E2位位置....如果E1具有有符号类型和负值,则结果值是实现定义的。”

因此,当x被签名为负数时,对于&lt;&lt;&lt;&lt;&lt;和实现 - 为&gt;&gt;定义。通常,对于带符号的x,如果只有x是非负的,代码将起作用。

答案 3 :(得分:0)

雅。它也可以在有符号整数上工作,因为这个代码与MSB上的符号位扩展无关&gt;&gt;转移。即,是否实现了符号位,它不会影响代码,因为它只涉及处理32位的X.只需存储并检索32位。所以由&gt;&gt;添加的位在MSB将不予考虑。要理解,请考虑 如果x是int x; //i.e。有符号整数然后

x = -1,即11111111 11111111 11111111 11111111

的ByteArray [0] = X; 11111111 11111111 11111111 11111111
  的ByteArray [1] = X&GT;&GT; 8; xxxxxxxx 11111111 11111111 11111111
  的ByteArray [2] = X&GT;&GT; 16; xxxxxxxx xxxxxxxx 11111111 11111111
  的ByteArray [3] = X&GT;&GT; 24; xxxxxxxx xxxxxxxx xxxxxxxx 11111111

由&gt;&gt;添加的位xxxxxxxx xxxxxxxx xxxxxxxx未被存储/使用,因此不会影响代码 因此,移位运算符的符号位扩展为done or not不会影响代码,因为从上面的示例可以清楚地看出,由x插入的位不用于存储。因此代码可以成功存储binartarray中的数字,并可以重新回到int x