以下是sockaddr_storage结构的定义(
rfc2553).根据rfc2553,sockaddr_storage
应与64位边界对齐,它应该能够同时保存sockaddr_in和sockaddr_in6.
此外,它必须有at __ss_family成员.其余字段是实现定义的.
应与64位边界对齐,它应该能够同时保存sockaddr_in和sockaddr_in6.
此外,它必须有at __ss_family成员.其余字段是实现定义的.
#define _SS_MAXSIZE 128 /* Implementation specific max size */ #define _SS_ALIGNSIZE (sizeof (int64_t)) /* Implementation specific desired alignment */ /* * Definitions used for sockaddr_storage structure paddings design. */ #define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof (sa_family_t)) #define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (sa_family_t)+ _SS_PAD1SIZE + _SS_ALIGNSIZE)) struct sockaddr_storage { sa_family_t __ss_family; /* address family */ /* Following fields are implementation specific */ char __ss_pad1[_SS_PAD1SIZE]; /* 6 byte pad,this is to make implementation /* specific pad up to alignment field that */ /* follows explicit in the data structure */ int64_t __ss_align; /* field to force desired structure */ /* storage alignment */ char __ss_pad2[_SS_PAD2SIZE]; /* 112 byte pad to achieve desired size,*/ /* _SS_MAXSIZE value minus size of ss_family */ /* __ss_pad1,__ss_align fields is 112 */ };
我的问题是为什么sockaddr_storage被定义为上面的方式?为什么不能定义如下?
struct sockaddr_storage { sa_family_t __ss_family; /* address family */ char __ss_pad[_SS_MAXSIZE - sizeof(sa_family_t) ]; //will there be any alignment issue here? };
解决方法
您提出的替代方案不会强制整个结构在8字节(64位)边界上对齐,您提到RFC2553的要求.
通常,结构采用其任何成员所要求的最严格的对齐.由于sa_family_t可能是u16_t,只需要2字节对齐,而char数组最多需要1字节对齐,因此您建议的替代方案只需要2字节对齐. (无论如何,编译器可能会给它至少4个甚至8个字节的对齐,但你无法确定.)
实际定义的样式是尝试确保结构中的每个字节都是某个命名字段的一部分,即编译器不在字段之间插入任何填充.这是必需的(有点),以便_SS_PAD2SIZE具有可以根据所有其他成员的大小计算的值.
但是,我发现这个定义相当复杂.我非常确定以下内容同样适用,并且更容易理解:
struct sockaddr_storage { union { sa_family_t u_family; uint64_t u_pad[_SS_MAXSIZE / sizeof(uint64_t)]; } __ss_u; # define __ss_family __ss_u.u_family };
这里,union获取其最严格对齐的成员的对齐要求,然后该成员传播到封闭结构.请注意,在这个版本中,我只有一个必填字段(虽然埋在一个联合中)和一个填充数组,它是我想要整个结构的确切大小.唯一有点棘手的部分是__ss_family的宏定义.宏技巧可能并不严格符合RFC中的要求,但很少有(如果有的话)注意到差异的方法.