我们可以使用static_assert来检测结构中的填充吗?
这是对另一个问题的后续行动
我试图在编译时建立一个特定的实现是否在结构中添加了未命名的填充。 像gcc这样的特定实现允许使用pragma来控制结构中的填充和对齐,但代价是与其他实现的兼容性。 由于C11的n1570草案都需要static_assert
和offset_of
,我想使用它们来查看实现是否在成员之间使用了填充。
以下是代码的相关部分(引用问题中的完整代码):
#include #include #include struct quad { int x; int y; int z; int t; }; int main() { // ensure members are consecutive (note 1) static_assert(offsetof(struct quad, t) == 3 * sizeof(int), "unexpected padding in quad struct"); struct quad q; ...
正如6.7.2.1结构和联合说明符§15所说:
在结构对象中,非位字段成员和位字所在的单元具有按声明顺序增加的地址。 指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然。 结构对象中可能存在未命名的填充,但不是在其开头。
我假设如果结构中元素的偏移量是在它之前声明的元素的大小的总和,那么这些元素之间不存在填充,并且它们应该连续分配,从而如果它们是相同类型则构成数组。
问题是:上述假设是错误的,它是(对参考问题的评论让我们思考)为什么?
理论上可能在t
之后的结构末尾填充,你的断言没有捕获(可能是也可能不是)。 您的假设是正确的,这是完全正确使用offsetof
和static_assert
,以检测成员变量之间的任何位置的填充。
更好的选择可能是:
static_assert( offsetof(struct quad, t) == sizeof(struct quad)-sizeof(int),
这也会在结构的末尾捕获填充。 此外,如果在代码维护期间更改结构成员,它会使断言更加灵活。