在 K&R2 中,他们在第 8 章中实现了内存分配器。对于每个 block ,都有像这样定义的 header (根据内存,代码可能不准确):
union header_t
{
struct
{
unsigned size;
unsigned* next;
};
long align;
};
他们这样做是为了“确保标题在 long 的边界上正确对齐”。但是 union 不是由最大的成员结盟吗?该结构比单个对齐成员大,因此 header 无论如何都会按结构的倍数对齐,不是吗?
当结构更大时(比如它有很多成员)呢?在编写内存分配器时是否总是需要这种对齐 union 技巧?
最佳答案
K&R中的数据类型是:
union header
{
struct
{
union header *ptr;
unsigned size;
} s;
Align x;
};
假设我们有这个:
union header_t
{
struct
{
union header_t *next;
unsigned size;
} s;
};
(顺便说一句,您需要为 struct
变量命名并更改
struct
中指向类型 union header_t *
的指针,因为
数据结构是一个链表。)
K&R的malloc()
实现预留了一 block 空间,然后
使用它来维护免费商店。当这个 malloc
被调用时,它
在空闲列表中找到一个有足够空间的地方,并返回一个
指向它尾端的指针。
特别是,代码的相关部分是:
typedef union header Header;
static Header base;
Header *p = &base;
...
p += p->s.size;
return (void *)(p+1);
请注意,我们将返回 p+1
(转换为 void *
),因此我们必须确保此指针对于任何数据类型都是对齐的 。由于 p
本身指向一个 Header *
,我们必须确保当我们将 sizeof(Header)
添加到一个对齐的指针时,我们返回另一个对齐的指针(记住,p+1
指向 p
中的 sizeof(Header)
字节)。此要求意味着 Header
必须针对所有类型的数据进行对齐。
Header
内的struct
可能未针对可能的最宽类型对齐。为了确保我们的 Header
类型如此对齐,我们向 union
添加一个我们知道最大对齐的成员,即,是给定机器上最宽的类型. K&R 假设此类型是long
。另外请注意,Header
的大小是否大于 Align
类型的大小并不重要。 这里的假设是这里的Align
类型是具有最严格对齐要求的类型,而不是它很大。
有趣的是,我们需要假设一个“最大对齐”类型,因为 C 标准要求对 malloc
返回的指针的任何类型进行对齐,但没有指定一种可移植的方法来找出对齐方式将是。如果标准确实指定了这样一种类型,则可以使用该类型而不是long
来实现Align
。
关于c - 内存分配头是否需要对齐 union ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1908024/