我的C中的字节是如何存储的?

时间:2012-05-17 22:06:03

标签: c memory storage

首先,我还是学生。所以我不是很有经验。

我正在使用蓝牙硬件,我正在使用其协议发送命令。该协议要求每个数据包字段首先使用LSB发送数据包。

我收到错误数据包回到我身上,表明我的CRC值是错误的,所以我做了一些调查。我发现了问题,但我在这个过程中感到困惑。

这是一些GDB输出和其他信息,说明我的困惑。

我发送的数据包应该是这样的:

|Start Flag| Packet Num | Command | Payload |    CRC    | End Flag|
    0xfc        0x1       0x0 0x8   0x0 0x5   0x59 0x42    0xfd

这是一些GDB输出:

print /x reqId_ep
$1 = {start_flag = 0xfc, data = {packet_num = 0x1, command = {0x0, 0x8}, payload = {
  0x0, 0x5}}, crc = 0x5942, end_flag = 0xfd}

reqId_ep是我正在发送的数据包的变量名。它看起来很好,但是我收到了它的CRC错误代码,所以一定是错的。

这里我从发送包的地址开始检查以十六进制形式的9个字节:

x/9bx 0x7fffffffdee0
0xfc    0x01    0x00    0x08    0x00    0x05    0x42    0x59    0xfd

这里问题变得明显了。 CRC不是LSB优先。 (0x42 0x59)

为了解决我的问题,我删除了我设置CRC值等于。

的htons()

以上是没有htons()的相同输出:

p/x reqId_ep

$1 = {start_flag = 0xfc, data = {packet_num = 0x1, command = {0x0, 0x8}, payload = {
  0x0, 0x5}}, crc = 0x4259, end_flag = 0xfd}

这里CRC值不是LSB。

但是:

x/9bx 0x7fffffffdee0
0xfc    0x01    0x00    0x08    0x00    0x05    0x59    0x42    0xfd

这里CRC值首先是LSB。

显然,C的存储首先是LSB?对于这种情况,有人可以向我提供一些知识吗?非常感谢你。

2 个答案:

答案 0 :(得分:4)

这与计算中的Endianness有关: http://en.wikipedia.org/wiki/Endianness#Endianness_and_operating_systems_on_architectures

例如,值4660(十进制)是十六进制的0x1234。在Big Endian系统上,它将作为1234存储在内存中,而在Little Endian系统上,它将存储为3412

如果你想在将来避免这类问题,最简单的方法是创建一个大型数组或unsigned char结构,并在其中存储单个值。

例如:

|Start Flag| Packet Num | Command | Payload |    CRC    | End Flag|
    0xfc        0x1       0x0 0x8   0x0 0x5   0x59 0x42    0xfd

typedef struct packet {
  unsigned char startFlag;
  unsigned char packetNum;
  unsigned char commandMSB;
  unsigned char commandLSB;
  unsigned char payloadMSB;
  unsigned char payloadLSB;
  unsigned char crcMSB;
  unsigned char crcLSB;
  unsigned char endFlag;
} packet_t;

然后,您可以创建一个函数,根据您使用预处理器宏构建的系统类型进行不同的编译。

例如:

/* Uncomment the line below if you are using a little endian system;
/* otherwise, leave it commented
 */
//#define LITTLE_ENDIAN_SYSTEM

// Function protocol
void writeCommand(int cmd);


//Function definition
void writeCommand(int cmd, packet_t* pkt)
{
  if(!pkt)
  {
     printf("Error, invalid pointer!");
     return;
  }

  #if LITTLE_ENDIAN_SYSTEM
    pkt->commandMSB = (cmd && 0xFF00) >> 8;
    pkt->commandLSB = (cmd && 0x00FF);
  # else  //  Big Endian system
    pkt->commandMSB = (cmd && 0x00FF);
    pkt->commandLSB = (cmd && 0xFF00) >> 8;
  #endif

  // Done
}

int main void() 
{
  packet_t myPacket = {0};  //Initialize so it is zeroed out
  writeCommand(0x1234,&myPacket);


  return 0;
}

最后一点说明:避免将结构作为数据流发送,而是一次一个地发送它的各个元素! ie:不要假设结构在这种情况下是内部存储的,就像一个巨大的无符号字符数组。编译器和系统有些东西就像打包和分配一样,结构实际上可能大于9 x sizeof(unsigned char)

祝你好运!

答案 1 :(得分:1)

这取决于架构,取决于您要定位的处理器。有一种所谓的“Big Endian”系统,它首先存储一个字的最高有效字节,而“Little Endian”系统首先存储最低有效字节。看起来你正在看那里的Little Endian系统。