【问题标题】:Can we use static_assert to detect padding in a struct?我们可以使用 static_assert 来检测结构中的填充吗?
【发布时间】:2018-01-08 10:33:40
【问题描述】:

这是其他question的后续行动

我试图在编译时确定特定实现是否在结构中添加了未命名的填充。像 gcc 这样的特定实现允许使用编译指示来控制结构中的填充和对齐,但代价是与其他实现兼容。由于 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 所说:

在结构对象中,非位域成员和位域所在的单元 驻留的地址按照声明的顺序增加。一个指针 适当转换的结构对象指向其初始成员(或者如果该成员是 位域,然后到它所在的单元),反之亦然。可能有未命名的 在结构对象内填充,但不在其开头。

我假设如果结构中元素的偏移量是在它之前声明的元素大小的总和,那么这些元素之间不能存在填充,它们应该被连续分配,因此如果它们是同类型。

问题是:上面的假设是错误的吗(参考问题上的 cmets 让我们想想)为什么?

【问题讨论】:

  • 免责声明:我知道这至少是一种极端情况,应该避免,但我真的很想了解我的假设在哪里是错误的。

标签: c struct static-assert


【解决方案1】:

理论上,t 之后的结构末尾可能有填充,您的断言没有捕获(这可能是也可能不是有意的)。您的假设在其他方面是正确的,这完全可以很好地使用 offsetofstatic_assert 来检测成员变量之间的任何填充。

更好的选择可能是:

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

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

【讨论】:

  • 感谢您的回答。我仍然想知道的是连续分配是否足以在 C 中构成一个数组 - referenced question 的对象是什么
  • @SergeBallesta 数组必须有连续的元素,但仅仅因为某些东西有连续的元素,它并不能使其成为数组类型。我也发布了您其他问题的答案。
  • 这个解决方案不是只检查结构末尾的填充(在最后一个值之后)吗?因为我认为 sizeof 在计算大小时考虑了填充字节。
猜你喜欢
  • 1970-01-01
  • 2020-07-24
  • 1970-01-01
  • 1970-01-01
  • 2015-11-07
  • 2022-11-13
  • 1970-01-01
  • 2011-01-02
相关资源
最近更新 更多