带有位字段的 C/C++ 结构体打包在缓冲区中

Posted

技术标签:

【中文标题】带有位字段的 C/C++ 结构体打包在缓冲区中【英文标题】:C/C++ struct with bits fields packing in buffer 【发布时间】:2016-02-11 19:59:27 【问题描述】:

我已经用位域定义了我的结构。

typedef struct
   unsigned char primero;
   unsigned int bit1: 1;
   unsigned int bit2: 1;
   unsigned char segundo;
   unsigned char array[4];
   unsigned int offset: 6;
 date;

我想通过这个特定的位顺序的套接字发送这些数据。

char auxsendbuf[BUF_SIZ];
memset(sendbuf, 0, BUF_SIZ);
date *st = (date *) auxsendbuf;

st->primero = 0x01;
st->bit1 = 1;
st->bit2 = 1;
st->segundo = 0x03;
st->array[0] = 0x04;
st->array[1] = 0x05;
st->array[2] = 0x06;
st->array[3] = 0x07;

我的问题是 bit1 和 bit2 用 0 填充以完成我不想发送的额外字节。结果是这样的……

01 03 03 04 05 06 07 00 50

我怎样才能强制咬合顺序?如果需要,我可以使用 C++。

【问题讨论】:

您通过网络发送的身份编码内容(带有位字段!)正在自找麻烦。 【参考方案1】:

您需要对字段进行分组,以便位域在一起:

typedef struct
   unsigned char primero;
   unsigned int bit1: 1;
   unsigned int bit2: 1;
   unsigned int offset: 6;
   unsigned char segundo;
   unsigned char array[4];
 date;

编辑:

如果您希望将所有位按原始顺序打包而不进行填充,则需要将位字段从中间的所有其他内容中取出:

typedef struct
   unsigned char primero;
   unsigned int bit1: 1;
   unsigned int bit2: 1;
   unsigned char segundo: 8;
   unsigned char array0: 8;
   unsigned char array1: 8;
   unsigned char array2: 8;
   unsigned char array3: 8;
   unsigned int offset: 6;
 date;

请注意,位域内不能有数组。

为什么你需要这个顺序的位?因为任何使用它的解决方案都会非常复杂。

【讨论】:

这只是我不想做的。我很自然地得到了同样的结果。我想将位 bit1 和 bit2 与 6 位字段 segundo 合并。我想将偏移量放在数据包的最后部分。 @XabiE 要实现这一点,您将不得不通过位移和掩码在位级别对数据包进行序列化。【参考方案2】:

编译器可以用你的位域做一些奇怪的事情。这基本上是一种“尽力而为”的方法,没有标准的方法来影响它。根据我的经验,最好将位域用于“消息映射”。声明您要发送的字节,然后自己进行位操作(设置和获取您需要的位)。

实际上,由于结构成员的大小、对齐和填充以及字节排序(对于多字节数据)可能存在问题,以确保完全安全,因此也不要使用结构。自己将消息打包并解包到一个字节数组中。只有在某些特定于应用程序的优化和一些检查(使用sizeofofsetoff 技巧)中,您才应该使用结构进行消息映射。

【讨论】:

以上是关于带有位字段的 C/C++ 结构体打包在缓冲区中的主要内容,如果未能解决你的问题,请参考以下文章

Python数据结构与算法(10)---二进制数据结构Struct

Python数据结构与算法(10)---二进制数据结构Struct

C/C++ 学习笔记:结构体中最后一个成员为[0]或[1]长度数组(柔性数组成员)的用法

C/C++ 学习笔记:结构体中最后一个成员为[0]或[1]长度数组(柔性数组成员)的用法

将整数转换为字符缓冲区以进行串行通信......? [关闭]

分散/聚集IO(scatter/gather)及iovec结构体