我们可以使用static_assert来检测结构中的填充吗?

Ser*_*sta 2 c struct static-assert

这是对另一个问题的后续行动

我试图在编译时建立一个特定的实现是否在结构中添加了未命名的填充.像gcc这样的特定实现允许使用pragma来控制结构中的填充和对齐,但代价是与其他实现的兼容性.由于这两个static_assertoffset_of被用于C11的n1570草案所要求的,我想用他们看到实现是否成员之间使用填充.

这是代码的相关部分(引用问题中的完整代码):

#include <stdio.h>
#include <stddef.h>
#include <assert.h>

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;
    ...
Run Code Online (Sandbox Code Playgroud)

正如6.7.2.1结构和联合说明符§15所说:

在结构对象中,非位字段成员和位字段所在的单元具有按声明顺序增加的地址.指向适当转换的结构对象的指针指向其初始成员(或者如果该成员是位字段,则指向它所在的单元),反之亦然.结构对象中可能存在未命名的填充,但不是在其开头.

我假设如果结构中元素的偏移量是在它之前声明的元素的大小的总和,那么这些元素之间不存在填充,并且它们应该连续分配,从而如果它们是相同类型则构成数组.

问题是:上述假设是错误的,它是(对参考问题的评论让我们思考)为什么?

Lun*_*din 5

理论上可能在结构的末尾有填充t,你的断言没有捕获(可能是也可能不是).你的假设是正确的,这是完全正确使用offsetofstatic_assert,以检测成员变量之间的任何位置填充.

更好的选择可能是:

static_assert( offsetof(struct quad, t) == sizeof(struct quad)-sizeof(int),
Run Code Online (Sandbox Code Playgroud)

这也会在结构的末尾捕获填充.此外,如果在代码维护期间更改了struct成员,它会使断言更加灵活.