在C++中的#pragma pack

3

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


这里是你需要的所有信息。它是通过搜索查询“pragma pack”在谷歌中排名第一的:http://msdn.microsoft.com/en-us/library/aa273913%28v=vs.60%29.aspx - bezmax
这与面向对象编程有什么关系? - Jörgen Sigvardsson
4个回答

13

#pragma pack指令可以控制结构体成员的对齐方式。默认情况下,通常是8字节对齐,确保长度不超过8字节的成员按其大小的倍数对齐。例如,双精度或64位指针。如果读取或写入未对齐的双精度数据,可能会导致性能下降,如果它跨越了CPU缓存行边界,则通常会慢三倍左右。此对齐方式可能会在成员之间产生未使用的空间,称为填充。

这种对齐方式通常不适用于网络数据帧,它们倾向于紧密地打包而没有任何填充,因此需要使用 #pragma pack(push, 1) 指令。


3
另一个要点是:如果结构体没有进行打包,而你想要建立一个(CRC)校验和,这将变得困难,因为你必须访问结构体的每个成员,而使用打包为1的结构体,你可以简单地访问结构体的所有字节。 - ur.

0

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


0

如果您只需要让两个具有相同设置的系统进行通信(测试等),则可以发送结构体,前提是它们只是POD(普通旧数据)(指针、虚拟表、std::strings等不能使用)。因此,不需要打包。

如果这些系统没有相同的设置(或者未知),则需要发送序列化协议中的数据,因此打包结构将无法实现。最简单的方法是检查是否有有效的协议可用。


0

编译器会“填充”结构体的字段和子字段,即在内存中用空白的内存块组织它们,这样做是为了增加效率,正如Hans Passant的回答所解释的那样。

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

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接