c - c中的内存对齐和填充
问题描述
考虑这个代码段
struct {
short x[5];
union {
float y;
long z;
} u;
} t;
假设类型为 , 的对象分别short
占用float
2long
个字节、4 个字节和 8 个字节。变量 t 的内存要求,不要忽略对齐考虑,是:
我不考虑对齐的尝试是 struct 将为 x 保留 10 个字节,因为每个大小为 2 个字节,长 z 为 8 个字节,因此总计将等于 18 个字节,但我想了解更多关于这种对齐的信息?
解决方案
我想知道这个内存对齐是如何工作的
来自 C 标准:
结盟
要求特定类型的对象位于存储边界上,其地址是字节地址的特定倍数
并进一步
对象对齐
完整的对象类型具有对齐要求,这对可以分配该类型对象的地址进行了限制。对齐是实现定义的整数值,表示可以分配给定对象的连续地址之间的字节数。对象类型对该类型的每个对象都有对齐要求
注意部分:实现定义
因此,允许 C 标准的实现对特定类型的对象可能位于的地址指定限制。
例如,它可能float
应该始终放置在 8 的倍数的地址上,即有效地址为 X * 8。因此 4000、4008、4016 有效,而 4001、4002、4003、4004、4005、4006、 4007 无效。
对于这样的实现,填充将被插入到结构中以获得有效地址。
对于您的示例:
如果您的编译器需要 8 字节对齐long
,则必须在 和 之间插入填充x
,z
以便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.x
t.y
t.x
t.z
推荐阅读
- sql - SQL组合来自不同表的总计列
- amazon-web-services - 将 AWS Managed Microsoft AD 与 Lambda 连接起来?
- java - 使用 Java FileSystems 删除 zip 中的多个文件
- java - 如何获得 int 分数以查看我的第二个活动
- go - 如何按顺序处理从某个用户到特定端点的并发请求
- reactjs - 删除 Redux-ORM 模型实例时出错(多对多)
- gps - 在这种 scrnaroo 中无法校准连接到车辆的磁力计,如图 8 校准
- database - MongoDB 排序操作的奇怪行为
- python-3.x - 从 sys.path 中删除无效引用
- ios - 如何在 RxSwift 中使用 tableView 的数据源(numberOfRowsInSection)?