我有两种结构,如下所示。注释指定了编译器将增加的数据成员的大小和填充值。
#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选项填充的编译器规则是什么?
答案 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,
您structure alignment should be equal to the alignment of its widest data member
的观点是错误的。