C 结构大小不一致

C struct sizes inconsistence

本文关键字:不一致 结构      更新时间:2023-10-16

可能的重复项:
如何找到结构的大小?
结构在内存大小上有所不同?

我使用以下结构进行网络通信,它在两者之间创建了许多不必要的字节。

它给出的大小与预期的 8 字节不同。

struct HttpPacket {
  unsigned char x1;
  union {
        struct {
           unsigned char  len;
           unsigned short host;
           unsigned char content[4];
        } packet;
        unsigned char bytes[7];
        unsigned long num;
    }

即使我正在从联合中删除字段,关注也会给出不同的大小

struct HttpPacket {
             unsigned char x1;
             union {
            struct {
               unsigned char  len;
               unsigned short host;
               unsigned char content[4];
            } packet;
            unsigned long num;
        }

另外,一个更清晰的例子

struct {
               unsigned char  len;
               unsigned short host;
               unsigned char content[4];
            } packet;

它给出的大小为 8,而不是 7。我再添加一个字段,它仍然给出相同的大小

struct {
               unsigned char  EXTRAADDEDFIELD;
               unsigned char  len;
               unsigned short host;
               unsigned char content[4];
            } packet;

有人可以帮助解决这个问题吗?

更新:我需要在传输数据包时保持格式,所以我想跳过这些填充

C 不保证struct的大小。 允许编译器根据需要排列成员。通常,在这种情况下,它将使大小字对齐,因为这在大多数机器上是最快的。

听说过对齐和填充吗?

基本上,为了确保快速访问,某些类型必须位于内存地址的某些边界上。
这称为对齐。

为此,允许编译器将字节插入数据结构以实现该对齐。
这称为填充。

默认情况下,结构字段在自然边界上对齐。 例如,4 字节字段将从 4 字节边界开始。 编译器插入填充字节来实现此目的。 可以通过使用 #pragma pack(0( 或其他类似的编译器指令来避免填充

如果你有一个C99编译器,并且可以使用"新的"固定宽度类型:创建一个uint8_t数组,并自己在成员中进行分离。

uint8_t data[8];
x1 = data[0];
len = data[1];
host = data[2] * 256 + data[3]; /* big endian */
content[0] = data[4];
content[1] = data[5];
content[2] = data[6];
content[3] = data[7];
/* ... */

如果您可以依赖 CHAR_BIT是 8,则可以在 C89 中遵循相同的过程。