【问题标题】:autoconf: check for offset of a memberautoconf:检查成员的偏移量
【发布时间】:2013-11-12 22:19:02
【问题描述】:

我有一个结构:

struct foo {
  struct {
     int a;
     int b;
     long len;
     unsigned short c;
     unsigned short d;
  };
  char payload[1024];
} bar;

我想在配置时找出是否需要插入填充以使“有效负载”双对齐。

Autoconf 提供了AC_CHECK_SIZEOF(type)AC_CHECK_ALIGNOF(type),但我真正需要的是AC_CHECK_OFFSETOF(type, member)。如果报告的偏移量不是双对齐的,我可以引入足够的填充来做到这一点。

我可以运行一个报告 offsetof(struct bar, payload) 的小测试程序,但我不想在我的构建系统中引入运行时检查(我们经常交叉编译)。

【问题讨论】:

    标签: c autoconf


    【解决方案1】:

    使用zero length bitfield 可能无需自动工具技巧即可解决此问题。

    struct foo {
      struct {
         int a;
         int b;
         long len;
         unsigned short c;
         unsigned short d;
      };
      int64_t : 0; // or long long whatever integer type is sizeof(double)
      char payload[1024];
    } bar;
    

    【讨论】:

    • 感谢您提供有关零长度位域的提示。但是,如果我正确阅读 XNU 示例,我想使用 double : 0 ?
    • @RobLatham 除非您的编译器将浮点位域作为某种扩展名,否则位域必须是整数类型...
    • @RobLatham 它需要一个整数类型,所以longint64_t 可能是合适的。
    • 感谢您提供一种不涉及配置魔法的方法。
    【解决方案2】:

    你可以使用AC_COMPUTE_INT:

    AC_COMPUTE_INT([payload_offset], [offsetof(struct bar, payload)], ...)
    

    但是使用匿名联合来强制对齐可能会更容易:

    struct foo {
      struct {
         int a;
         int b;
         long len;
         unsigned short c;
         unsigned short d;
      };
      union {
        char payload[1024];
        double dummy; /* for alignment */
      };
    } bar;
    

    如果您不想使用联合,则可以就地计算填充:

    struct foo {
      struct header {
         int a;
         int b;
         long len;
         unsigned short c;
         unsigned short d;
      };
      char padding[(alignof(double) - 1) - ((sizeof(struct header)
          + alignof(double) - 1) % alignof(double))];
      char payload[1024];
    } bar;
    

    【讨论】:

    • 在这两种方法中,零宽度位域或存储到联合中,哪一种是更标准的方法,如果可以这样说,那么这样做?
    • @RobLatham 零宽度位域可以强制填充到整数类型的对齐,但不是浮点类型。自 C11 起,匿名联合是标准 (6.7.2.1p13) 的一部分,并得到广泛支持。
    • 我们仍在努力维护 c89,但也许命名联合会起作用。
    • 感谢您的回答。我选择了零宽度位域方法,因为它在较旧的 c 环境中可用。
    【解决方案3】:

    我真的不认为 autoconf 可以告诉你,因为这是编译器决定添加或不添加填充的问题。所以我认为唯一合理的方法是编译一个程序来检查成员的偏移量是否等于你认为应该相等的值。

    【讨论】:

    • 毫无疑问,答案完全取决于编译器。 AC_CHECK_SIZEOF 和 AC_CHECK_ALIGNOF 完全按照您的建议确定答案:通过编译程序。我缺少的技巧是如何在不运行该程序的情况下获得答案。
    • 好吧,然后使用静态断言,这会在编译时破坏程序。类似于: char x [(expr) ? 1 : -1];
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-02
    • 2014-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多