【问题标题】:Is alignment of struct types defined in C?结构类型的对齐是否在 C 中定义?
【发布时间】:2015-02-17 12:41:05
【问题描述】:

我知道 C 结构中的成员与他们需要的任何边界对齐。

struct S {
  uint8_t ui8;
  /* invisible padding here */
  uint32_t ui32;
};

我的问题是struct S 实例的对齐方式是否已定义?

struct S my_s; 

my_s 的对齐是否已定义? struct S 是否将 ui32 作为其第一个成员是否重要?

我已经搜索过,但只找到了关于结构成员对齐的信息。

【问题讨论】:

    标签: c struct memory-alignment


    【解决方案1】:

    是的,它有对齐要求,是的,它取决于struct 的成员的类型。

    C11 草案规范说:

    完整的对象类型有对齐要求,这会造成限制 在可以分配该类型对象的地址上。

    和:

    完整类型的对齐要求可以使用 _Alignof 表达式。

    【讨论】:

    • it might depend on the type(s) of the member(s),可能吗?还有什么条件?
    • @nouney 它也可以依赖于#pragmas 等的使用,但这过于谨慎。我编辑了,谢谢。
    【解决方案2】:

    答案:不在 C99 中。是的,在 C11 中。参考answer from unwind

    在所有已知平台上的 C99 实践中,您可以确定类型的对齐方式:

    #include <stddef.h> //Defines offsetof(.,.) 
    
    #define alignmentof(TYPE) offsetof(struct { char w; TYPE v;},v)
    

    C 标准对如何填充结构几乎没有规定,除了可以,它们不能在开头填充,但可以在中间和结尾填充,并且必须在没有元素间填充的数组中正确对齐.

    实际上,没有人(我发现)提出了一个真正的平台,除了不填充(所谓的压缩)或最小填充以遵守底层硬件上数据类型的对齐方式之外,它们还没有被填充。

    自然的填充例程是:

    1. 将第一个成员放在开头(这是一项严格要求)。
    2. 最少填充到下一个成员的对齐位置并插入它。
    3. 对所有剩余成员重复此操作。
    4. 最少添加结束填充以确保structsizeof 是最严格对齐的成员对齐的倍数。

    如前所述,实际上,如果发生填充,就会发生这种情况(据我的非正式调查发现)。

    【讨论】:

      【解决方案3】:

      是的……

      struct S {
        uint8_t ui8;
        /* invisible padding here */
        uint32_t ui32;
      };
      

      大小 = 8

      该结构包含一个 4 字节的 uint32_t,因此 struct 将与 4 字节对齐

      假设它从 0x0 开始 让我们看看

      0x0 = ui8
      0x1 = padding
      0x2 = padding
      0x3 = padding
      0x4 = ui32
      

      如果假设我们在开始时添加一个 uint32_t 那么它会变成......结构看起来像

      struct S {
        uint32_t ui32_2;
        uint8_t ui8;
        /* invisible padding here */
        uint32_t ui32;
      };
      

      然后

      0x0 = ui32_2
      0x4 = ui8
      0x5 = padd
      0x6 = padd
      0x7 = padd
      0x8 = ui32
      

      结构保持对齐等于它包含的最大大小的成员。在这种情况下,结构将始终从地址开始

      地址 %4 == 0

      【讨论】:

      • 差不多。一些平台不对齐数据,在这种情况下填充会消失。 uint32_t 的对齐也可能是 2,在这种情况下,需要的填充字节数会少 2 个。我不知道在两个字节边界上对齐uint32_t 的平台!但这是可能的。无论如何都赞成如此详细的答案。
      • @DanAllen:如果尝试访问不是 16 位对齐但可以满足来自任何一对连续 16 位字的 32 位请求,不考虑 32 位对齐。这样的设计使编写代码变得容易,例如通过使用 32 位加载来获取背景,绘制移动 0 到 15 位的对象,然后使用 32 位存储,在任意 X 偏移处绘制一个 16 像素的对象。
      猜你喜欢
      • 2013-10-16
      • 1970-01-01
      • 2011-10-10
      • 2012-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-25
      • 2011-01-18
      相关资源
      最近更新 更多