具有灵活阵列成员的打包结构的便携式替代方案
Portable alternative for packed structures with a flexible array member
假设我们正在使用 UDP 套接字编写 C++ 网络应用程序。我们需要传递一个不太小的数据包,所以我们使用了这种结构,确保字节顺序是网络顺序:
struct [[gnu::packed]] datagram {
uint64_t timestamp;
uint8_t type;
uint32_t temperatures[60]; // whatever, just an example
uint8_t raw_data[];
};
我们使用的是 GNU GCC,因此我们利用了非标准的 C++ 功能,例如
- 灵活的数组成员
- 压缩结构
我们需要一个打包结构,因为我们不希望在两者之间进行填充,因为这可能取决于体系结构,并且我们的网络程序可能 运行 在不同的体系结构上。
然后,一年后,可能会发现我们需要支持一个不支持这些的非 GCC 编译器。
是否可以在标准 C++ 中执行此操作?
当然,我知道我们可以简单地使用 uint8_t buffer[SOME_SIZE]
和 memcpy 数据报的每一部分,但这听起来是创建可怕、非常丑陋代码的好方法。
[[gnu::packed]]
是在任意架构之间进行序列化的糟糕方式。那里仍然有大端机器。
正确的做法是根据八位字节定义序列化格式,然后在八位字节流(往返于 UDP 套接字)和排列良好的结构之间进行转换。
有很多库可以让这变得简单。我们在工作中使用 protobuf
;以前的雇主有一个自制的解决方案。 (请注意,对此类库的推荐请求对于 Stack Overflow 来说是明确的题外话。)
假设我们正在使用 UDP 套接字编写 C++ 网络应用程序。我们需要传递一个不太小的数据包,所以我们使用了这种结构,确保字节顺序是网络顺序:
struct [[gnu::packed]] datagram {
uint64_t timestamp;
uint8_t type;
uint32_t temperatures[60]; // whatever, just an example
uint8_t raw_data[];
};
我们使用的是 GNU GCC,因此我们利用了非标准的 C++ 功能,例如
- 灵活的数组成员
- 压缩结构
我们需要一个打包结构,因为我们不希望在两者之间进行填充,因为这可能取决于体系结构,并且我们的网络程序可能 运行 在不同的体系结构上。
然后,一年后,可能会发现我们需要支持一个不支持这些的非 GCC 编译器。
是否可以在标准 C++ 中执行此操作?
当然,我知道我们可以简单地使用 uint8_t buffer[SOME_SIZE]
和 memcpy 数据报的每一部分,但这听起来是创建可怕、非常丑陋代码的好方法。
[[gnu::packed]]
是在任意架构之间进行序列化的糟糕方式。那里仍然有大端机器。
正确的做法是根据八位字节定义序列化格式,然后在八位字节流(往返于 UDP 套接字)和排列良好的结构之间进行转换。
有很多库可以让这变得简单。我们在工作中使用 protobuf
;以前的雇主有一个自制的解决方案。 (请注意,对此类库的推荐请求对于 Stack Overflow 来说是明确的题外话。)