当前位置: 首页 > 知识库问答 >
问题:

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

欧阳成弘
2023-03-14

这是另一个问题的后续问题

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

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

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

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

共有1个答案

周马鲁
2023-03-14

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

更好的选择可能是:

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

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

 类似资料:
  • 问题内容: 可用于添加特定字符的前缀。 我可以这样做,例如: 它的长度为32,并用0左填充: sendID 相似时如何实现相同的目的: 我想要这样的输出: 问题答案: 您可以使用这种怪异的方式来获取输出: 演示:http://ideone.com/UNVjqS

  • 问题内容: 我可以从数组中读取每种语法的数据: 但是有可能同样填充数组。说,有价值观? 我没有发明这样的方法,而是想问你我是否错。 问题答案: 在Java Docs中 , for-each循环隐藏了迭代器,因此您无法调用remove。因此,for-each 覆盖绝大多数案例。 因此,简单来说,不可能填充数组。

  • 问题内容: 我正在传递一个accountid作为XML文件的输入,如图所示,稍后将对其进行解析并将在我们的代码中使用: 问题是,如果没有传递任何内容(accoutnid中的空值)作为accountid传递,我将无法在Java代码中处理这种情况。我尝试了这个,但是没有成功: 我可以使用以下方法成功解决此问题: 我们可以依靠该方法来检查a的空条件吗?这有效吗? 问题答案: 不,绝对不是-因为如果为nu

  • 问题内容: 我已经阅读了有关ES的关于版本管理的博客文章。 但是,我希望能够从更新中获取以前的“ _souce”文档。 例如,假设我有这个对象: 我将其更新为: 然后,通过ES中的版本控制,我能否获得对象的先前的“ job”属性?我已经试过了: 但这只会返回最新的_source对象(John担任总裁的对象)。 我实际上想实现版本差异方面,就像StackOverflow一样。(顺便说一句,我正在使用

  • 下图代表房间布局。 “#”代表墙。在左边和右边有#的单个空格代表门。连续的空间代表房间面积。 这将作为一个2D数组提供给Java程序。示例输入如下:

  • 我正在使用BeautifulSoup刮取一个URL,并使用以下代码查找标记,其类为: 现在,在上面的代码中,我们可以使用获取标记和与它们相关的信息,但我想使用XPath。是否可以将XPath与BeautifulSoup一起使用?如果可能,请给我提供示例代码。