为什么打包结构5的大小而不是4个字节?

Pri*_*alj 8 c c++ gcc struct bit-fields

参见在线示例: Ideone示例

struct {
  union {
    struct {
      uint32_t messageID : 26;
      uint8_t priority : 3; 
    } __attribute__ ((packed));
    uint32_t rawID : 29;
  } __attribute__ ((packed));
  uint8_t canFlags : 3;
} __attribute__ ((packed)) idSpecial;
Run Code Online (Sandbox Code Playgroud)

为什么编译器会将结构的大小报告为5个字节而不是4个?它应该包含32位.

use*_*342 6

问题是__attribute__((packed))不执行按位打包.它只是保证struct成员之间没有填充.您可以尝试这个更简单的示例,其中size也报告为5:

typedef struct structTag {
    struct {
      uint32_t messageID : 26;
      uint8_t priority : 3;
    } __attribute__ ((packed));
    uint8_t canFlags : 3;
} __attribute__ ((packed)) idSpecial;
Run Code Online (Sandbox Code Playgroud)

按位打包仅适用于位域成员.您需要将结构重新设计为结构与bitfields messageID/priority/canFlags的结合,以及带有bitfields rowID/canFlags的结构.换句话说,您需要有一些重复或使用访问器宏或成员函数.


T.J*_*der 5

这是因为内存对齐:编译器不会canFlags在一个字节的中间启动,它会在下一个字节的开头(可能是*)启动它.所以你的初始联合有四个字节,一个字节canFlags.

例如,如果你canFlags进入了联盟,那么它(可能是*)的大小为4:

typedef struct structTag {
  union {
    struct {
      uint32_t messageID : 26; /* 26bit message id, 67108864 ids */
      uint8_t priority : 3; /* priority: MUST BE 0 */
    } __attribute__ ((packed));
    uint32_t rawID : 29;
    uint8_t canFlags : 3; /* <==== Moved */
  } __attribute__ ((packed));
} __attribute__ ((packed)) idSpecial;
Run Code Online (Sandbox Code Playgroud)

有关ideone的更新示例.显然,这种具体的变化可能不是你想要的; 我只是在证明问题是在字节边界上开始一个新字段.


*"可能"因为最终取决于编译器.