【问题标题】:C Are arrays in structs aligned?C 结构中的数组是否对齐?
【发布时间】:2014-10-21 14:33:55
【问题描述】:
struct {
    uint8_t foo;
    uint8_t bar;
    uint8_t baz;
    uint8_t foos[252];
    uint8_t somethingOrOther;
} A;

struct {
    uint8_t foo;
    uint8_t bar;
    uint8_t baz;
    uint8_t somethingOrOther;
    uint8_t foos[252];
} B;

我在第一个示例中将 foos 放在字节 3 上,而不是在 B 中的字节 4 上,这有关系吗?

C 中的数组是否必须开始对齐?

这个结构的大小正好是 256 字节吗?

【问题讨论】:

    标签: c alignment


    【解决方案1】:

    鉴于数据类型为uint8_t(等价于unsigned char),无论结构如何排序,都不需要填充。因此,在这种情况下,您可以合理地假设每个编译器都会将该结构制成 256 个字节,而不管元素的顺序如何。

    如果有不同大小的数据元素,那么您很可能会添加填充,并且结构的大小可能会根据元素的顺序而有所不同。

    【讨论】:

      【解决方案2】:

      正如the good book 所说(C11 第 6.7.2.1 节第 14 段):

      结构或联合对象的每个非位域成员都对齐 一种适合其类型的实现定义的方式......那里 可能是结构对象中的未命名填充

      您没有“将foos 放在字节 3 上” - 除了第一个元素始终位于字节 0 上之外,您无法真正控制元素将放在哪个字节上。编译器可以给每个字段一个完整的机器字或更多,如果它认为这将提供最有效的访问。如果是这样,它将在两者之间分配“填充”字节 - 未使用的空间。

      请注意,这仅适用于结构;数组本身不添加任何填充字节(如果添加了,指针算术/索引规则将不起作用),因此您可以确定 foos 本身的大小正是声明的大小,并且知道精确对齐每个编号的元素。

      【讨论】:

        【解决方案3】:

        不,没关系。

        几乎每个编译器都会将struct 字段与适合目标架构的自然边界对齐,方法是在必要时在字段之间插入隐藏的“填充字节”。

        具体来说,由于您只使用uint8_t,因此不会插入任何填充字节 - 每个字段都已落在自然对齐的边界上。 (一切都是一的倍数。)

        您显示的两个structs 的大小都是256 字节。您可以这样确认:

        int main(void)
        {
            printf("sizeof(struct A)=%zu \n", sizeof(struct A));
            printf("sizeof(struct B)=%zu \n", sizeof(struct B));
        }
        

        您可以通过“打包”结构来防止添加此填充:

        请注意,在具有未对齐成员的结构上执行此操作可能会对您的程序的性能产生严重影响。

        【讨论】:

        • 第二部分是我感兴趣的,我希望实现无填充。谢谢!
        • 假设我创建了一个由这些结构组成的数组,并且该数组也正确对齐,我假设不会因为填充而浪费空间?
        • @CodySmith:正确。结构的基本大小使得结构的数组也将正确对齐。鉴于struct x { long double d; char c; };long double 的对齐要求意味着在c 元素之后将有填充,以便数组的下一个元素正确对齐。
        • @CodySmith 您可以通过在测试程序中使用offsetof 来确认。
        猜你喜欢
        • 1970-01-01
        • 2023-03-27
        • 2018-09-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-23
        • 2013-06-03
        • 2012-10-28
        相关资源
        最近更新 更多