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

Can we use static_assert to detect padding in a struct?

这是另一个

的后续

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

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

#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;
    ...

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

Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.

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

问题是:上面的假设是不是错了,是吗(参考问题有什么评论让想想)为什么?

理论上可能会在 t 之后的结构末尾进行填充,您的断言没有捕捉到(这可能是有意的,也可能不是有意的)。您的假设在其他方面是正确的,这非常适合使用 offsetofstatic_assert,来检测成员变量之间的任何位置的填充。

更好的选择可能是:

static_assert( offsetof(struct quad, t) == sizeof(struct quad)-sizeof(int),

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