结构体填充

5

我正在学习C语言中的结构体填充和压缩。 我有一个疑问,由于我已经了解到填充取决于计算机架构,那么它会影响跨机器通信吗?也就是说,如果在一台计算机上创建的数据被另一台计算机读取,会出现什么问题。 在这种情况下,如何避免这个问题。

5个回答

6
是的,您不能在平台之间发送结构的二进制数据并期望它在另一端看起来相同。解决方法是为您的构造创建一个编组器/解组器,并在离开一个系统时通过它传递,在进入另一个系统时也是如此。这样,编译器就可以在每个系统上为您处理缓冲区了。
每一方都知道如何接收数据,因���您已经指定了它将被发送,并且将其用于本地平台。
像Java这样的平台会为您的类创建序列化机制。在C中,您需要自己做到这一点。如何做取决于您想要发送数据的方式。您可以序列化为二进制、XML或其他任何格式。

2

这是事实,但在网络通信或跨平台共享文件的背景下,这种说法极其误导。 - Ben Jackson
是的,您可以更改结构填充。 这可能很危险。 一些 API 要求数据对齐。更改填充可能会破坏这种对齐性。 - Anthony
改变结构填充并不足以确保在不同的机器上解释数据相同。还有许多其他问题,例如浮点数/双精度数的表示方式、有符号整数的表示方式、整数的字节顺序、数据类型的大小(charintlonglong long等),以及更多其他问题。 - Anthony
这个问题特别涉及到填充(padding)。显然还有其他问题需要考虑;在我看来,字节序(endianness)是接下来要考虑的一个问题。如果你能确保典型架构下匹配的结构体(structure pack)、字长(word size)和字节序(endianness),那么此时你就可以了。 - StilesCrisis
@StilesCrisis 是的,但用户问的是关于机器间通信的问题。我认为他们应该知道结构填充不是唯一需要考虑的问题。 - Anthony
这就是为什么我直接建议使用显式序列化机制的原因。这将强制处理每个元素,确保每个部分都可以单独处理,并使故障排除更容易。 - xaxxon

1
在C/C++中,结构体被用作数据包。它不提供任何数据封装或数据隐藏功能(C++是一个例外,因为它与类的语义相似)。由于各种数据类型的对齐要求,结构体的每个成员都应该自然对齐。结构体的成员按顺序递增分配。

0

只有在你编译用于其他架构的代码使用了不同的填充方案时,才会受到影响。

为了帮助缓解问题,我建议您使用无填充的结构体。在需要填充时,请使用占位符(例如char reserved[2])。此外,请勿使用位字段!它们不具备可移植性。

您还应该注意其他与架构相关的问题。特别是字节序和数据类型大小。如果需要更好的可移植性,您可能希望将其串行化和反串行化为一个字节流,而不是将其强制转换为struct


0
您可以在结构声明之前使用#pragma pack(1),并在其后使用#pragma pack()来禁用基于架构的对齐方式。这将解决问题的一半,因为某些数据类型也是基于架构的。要解决第二个问题,我通常会使用特定的数据类型,如int_16表示16位整数,u_int_32表示32位整数等等。
请参考http://freebsd.active-venture.com/FreeBSD-srctree/newsrc/netinet/ip_icmp.h.html 。其中包括一些独立于架构的网络数据包的说明。

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