3

为什么我们需要在 C++#pragma pack中使用结构?typedef特别是当您在网络通信中使用这些结构时。

4

4 回答 4

13

#pragma pack控制结构成员的对齐方式。常见的默认设置为 8,确保最长为 8 个字节的成员在其大小的倍数的地址上对齐。例如双精度或 64 位指针。读取或写入未对齐的 double 可能会非常昂贵,如果它跨越 CPU 缓存线边界,通常会慢三倍。这种对齐会在成员之间产生未使用的空间,称为填充。

这种对齐方式通常不适合网络框架,它们往往被紧密打包而没有任何填充,#pragma pack(push, 1)

于 2010-12-22T09:34:47.280 回答
0

编译器将“填充”结构的字段和子字段,即,将它们组织在内存中,中间没有任何内容的空白内存块。正如 Hans Passant 的回答所解释的那样,这样做是为了提高效率。

不同的编译器/目标/优化设置可能会以不同的方式填充,将相等的“逻辑”结构转换为不相等的内存表示,因此如果两台通信机器在它们之间传递结构,它们可能无法相互理解。

#pragma pack 是限制编译器填充自由的方法。

#pragma pack(push, 1) 命令编译器根本不填充。如果对不同代码中定义的两个相同结构执行此操作,它们将在内存中以相同的方式表示。然后,您可以使用指针和 sizeof() 通过某种协议安全地在一个应用程序中发送结构的内容,在另一端获取它并将其直接写入相同的结构,也使用指针和 sizeof()。

于 2010-12-22T09:47:55.943 回答
0

如果您只需要让具有相同设置的 2 个系统相互通信(测试,...),您可以发送结构,只要它们只是 POD(普通旧数据)(指针、虚拟表、std::strings.. . 不能使用)。所以不需要打包。

如果系统没有相同的设置(或未知),您需要发送在协议中序列化的数据,因此打包结构不会这样做。检查是否有有效的协议是最容易的。

于 2010-12-22T09:44:36.330 回答
0

#pragma pack 指令仅修改其声明遵循指令的结构成员的当前对齐规则。它不直接影响结构体的对齐方式,但是通过影响结构体成员的对齐方式,可能会根据对齐规则影响整个结构体的对齐方式

于 2010-12-22T09:26:50.707 回答