使用uint64_t的32位和64位架构的结构填充差异

时间:2018-03-20 06:30:56

标签: c gcc struct padding

我有两种结构,如下所示。注释指定了编译器将增加的数据成员的大小和填充值。

#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 个答案:

答案 0 :(得分:2)

在32位机器上,处理字大小为4个字节,因此结构根据您将PEER_MSG的大小设置为28个字节的原因进行对齐。在64字节系统上,由于处理字大小为8字节,因此PEER_MSG的大小为32字节。

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

答案 1 :(得分:1)

My question is: with -m32 option, size of uint64_t remains 8 bytes, but the alignment of the structure PEER_MSG is of 4 bytes,

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

structure alignment should be equal to the alignment of its widest data member的观点是错误的。

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