在字节缓冲区中复制结构

Posted

技术标签:

【中文标题】在字节缓冲区中复制结构【英文标题】:Copy a struct inside a byte buffer 【发布时间】:2016-07-28 19:26:41 【问题描述】:

我有以下结构:

struct sample 
  uint8_t four;
  bool    b;
  uint8_t two;
;

为了发送一个udp数据包,我需要将这些值打包成一个字节:

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+---+---+---+---+---+---+---+---+
|     four      | 0 | b |  two  |
+---------------+---+---+-------+

在这个字节中复制结构值的最佳方法是什么?我在这样做之前检查了前提条件,因此在将 uint8_t 值复制到更小的空间时不会丢失任何数据。

【问题讨论】:

【参考方案1】:

我只想使用一个函数:

uint8_t pack( const sample &s )

    return ( s.four & 0xF ) | ( s.b << 5 ) | ( ( s.two & 3 ) << 6 );

正如您所说,检查了数据范围,您可以将其简化为:

    return s.four | ( s.b << 5 ) | ( s.two << 6 );

【讨论】:

【参考方案2】:

由于您的代码无论如何都不可移植,因此您不妨在这里使用位域:

struct sample 
  uint8_t four:4;
  bool    empty:1;   
  bool    b:1;
  uint8_t two:2;
;

我不喜欢位字段,但它们似乎适用于您的情况。

【讨论】:

不应该empty 出现在b 之前吗? 为什么不便携? 因为你要对 uint8_t 进行实体序列化,而那是不可移植的。【参考方案3】:

您的位顺序以...独特的方式显示。通常当我们用二进制表示值时,低位显示在右侧。只要您在打包和解包数据,您就可以选择您的位顺序。不过要注意网络顺序与系统顺序。虽然每个平台的字节内位顺序都是相同的,但字内字节顺序可以改变。

您必须了解您的应用程序才能确定打包/拆包是否值得。在每一侧进行更多的计算,并且取决于 UDP 数据包之间的间隔以及每个 UDP 数据包中包含多少数据,这可能不值得。如果您只是想为蜂窝应用程序保存数据,那么,谢谢 :@)

由于平台/编译器偏执,我总是避免转换布尔值。可以改用 s.b?32:0 之类的东西。

【讨论】:

我正在尝试创建 CIGI 数据包,标准有很多以这种方式构建的数据包... 抱歉,有点脑残。网络数据包总是这样写的

以上是关于在字节缓冲区中复制结构的主要内容,如果未能解决你的问题,请参考以下文章

在结构或类中使用智能指针

无法将固定大小的字节数组从结构复制到 C# 结构中的另一个数组

复制缓冲区中的 IP 地址

c_cpp 将int复制到字节缓冲区

Python 3.8 结构解包 - struct.error: unpack 需要 1 个字节的缓冲区

IO流 - 复制文件(字节缓冲流+字节流)