提问者:小点点

32 位和 64 位体系结构中的结构填充差异,带uint64_t


我有两个结构,如下所述。注释指定数据成员的大小和编译器将扩充的填充值。

#include <stdio.h>
#include <stdint.h>


typedef struct peer_msg_hdr
{
  char type;            /**< 1 */
                        /**< pad[3] */
  uint32_t id;          /**< 4 */
  uint64_t timestamp;   /**< 8 */
} PEER_MSG_HDR;         /**< 16 */

typedef struct peer_msg 
{
  PEER_MSG_HDR hdr;      /**< 16 */
  uint16_t listen_port;  /**< 2 */
                         /**< pad[2] */

  uint32_t num_nodes;    /**< 4 */
  uint32_t num_proc;     /**< 4 */
} PEER_MSG;


int main()
{
  printf("%lu\n", sizeof(PEER_MSG));
  return 0;
}

现在在一台x86_64主机中,首先我计算PEER_MSG的大小。原来是32岁。接下来,如果我在 gcc 中使用 -m32 选项计算大小,则大小为 28。

这两者之间的差异出现在最后一个数据成员 num_proc 之后的填充中。在 -m32 选项编译的情况下,没有填充。但是如果没有 -m32 选项,则有一个 4 个字节的填充(将整个结构对齐为 8 个字节,因为最宽的数据成员大小为 8 个字节(uint64_t 时间戳))。

我的问题是:使用 -m32 选项,uint64_t 的大小仍然是 8 个字节,但结构PEER_MSG的对齐方式是 4 个字节,这与填充的一般规则相矛盾(结构对齐方式应等于其最宽数据成员的对齐方式)。那么这里使用 -m32 选项填充的编译器规则是什么?


共2个答案

匿名用户

在 32 位机器上,处理字大小为 4 个字节,因此结构根据 28 字节的大小对齐,这就是为什么你得到 PEER_MSG 的大小为 28 字节。在 64 字节的系统上,由于处理字的大小为 8 个字节,因此PEER_MSG的大小为 32 个字节。

当您指定 -m32 选项时,编译器将假定最终可执行文件将在 32 字节系统上运行,因此会适当地进行填充。

匿名用户

我的问题是:使用 -m32 选项,uint64_t的大小仍然是 8 个字节,但结构PEER_MSG的对齐方式是 4 个字节,

  • 这是完全正确的。在 32 位系统中,uint64_t的大小也是 8 字节。结构藻是基于字大小 4 字节完成的。

您的结构对齐点应等于其最宽数据成员的对齐是错误的。

  • 结构藻类基于体系结构的字大小(不是最广泛的数据成员)。在 32 位架构中,字大小为 4 字节,而在 64 位架构中,字大小为 8 字节。