首页 > 解决方案 > c中的内存对齐和填充

问题描述

考虑这个代码段

struct {
    short x[5];  
    union { 
        float y; 
        long z; 
    } u;
} t;

假设类型为 , 的对象分别short占用float2long个字节、4 个字节和 8 个字节。变量 t 的内存要求,不要忽略对齐考虑,是:

我不考虑对齐的尝试是 struct 将为 x 保留 10 个字节,因为每个大小为 2 个字节,长 z 为 8 个字节,因此总计将等于 18 个字节,但我想了解更多关于这种对齐的信息?

标签: c

解决方案


我想知道这个内存对齐是如何工作的

来自 C 标准:

结盟

要求特定类型的对象位于存储边界上,其地址是字节地址的特定倍数

并进一步

对象对齐

完整的对象类型具有对齐要求,这对可以分配该类型对象的地址进行了限制。对齐是实现定义的整数值,表示可以分配给定对象的连续地址之间的字节数。对象类型对该类型的每个对象都有对齐要求

注意部分:实现定义

因此,允许 C 标准的实现对特定类型的对象可能位于的地址指定限制。

例如,它可能float应该始终放置在 8 的倍数的地址上,即有效地址为 X * 8。因此 4000、4008、4016 有效,而 4001、4002、4003、4004、4005、4006、 4007 无效。

对于这样的实现,填充将被插入到结构中以获得有效地址。

对于您的示例:

如果您的编译器需要 8 字节对齐long,则必须在 和 之间插入填充xz以便z从 8 字节对齐地址开始。大小将是 24 字节。

但请记住,这是实现定义的。

你可以试试这个程序:

#include <stdio.h>
 
struct { 
    short x[5];  
    union { 
        float y; 
        long z; 
    } u;
}t;
 
int main(void) {
    printf("Size of t     is %zu\n", sizeof(t));
    printf("Size of t.x   is %zu\n", sizeof(t.x));
    printf("Size of t.u.y is %zu\n", sizeof(t.u.y));
    printf("Size of t.u.z is %zu\n", sizeof(t.u.z));
    printf("Location of t   is %p\n", (void*)&t);
    printf("Location of t.x is %p\n", (void*)t.x);
    printf("Location of t.y is %p\n", (void*)&t.u.y);
    printf("Location of t.z is %p\n", (void*)&t.u.z);
    return 0;
}

可能的输出:

Size of t     is 24
Size of t.x   is 10
Size of t.u.y is 4
Size of t.u.z is 8
Location of t   is 0x559b60552020
Location of t.x is 0x559b60552020
Location of t.y is 0x559b60552030
Location of t.z is 0x559b60552030

请注意, 的大小为 10,但和t.x之间的地址距离为 16(又名 0x10),因此和之间有 6 个字节的填充。t.xt.yt.xt.z


推荐阅读