在C标准中,
malloc
函数的定义简洁,没有明确规定任何关于对齐的内容。下面是摘自C23标准的概要,其与之前版本基本相似,只有章节编号发生了变化:
7.24.3.6 The malloc function
Synopsis
#include <stdlib.h>
void *malloc(size_t size);
Description
The malloc
function allocates space for an object whose size is specified by size
and whose representation is indeterminate.
Returns
The malloc
function returns either a null pointer or a pointer to the allocated space.
关于块对齐要求,直到C17为止,这在父章节的开头被指定如下:
7.22.3 内存管理函数
[...]
如果分配成功,则返回的指针将适当地对齐,以便将其赋值给具有基本对齐要求的任何类型对象的指针,并用于访问该对象或该对象数组中的对象(直至显式释放空间)。
这意味着对于所有的基本类型,如int、long、long long等,malloc(1)必须正确对齐,并且对于在分配的空间中访问这些对象存在一定的歧义。
作为一个缺陷进行了报告,这个问题在C23中得到了
讨论,并且文本已经修正以放宽此要求并澄清这个歧义(重点是我的)。
7.24.3 内存管理函数
[...]
如果分配成功,则返回的指针将适当地对齐,以便可以将其赋值给具有基本对齐要求且大小小于或等于所请求大小的任何类型对象的指针。然后,它可以用于访问在分配的空间中的此类对象或此类对象的数组(直到显式释放该空间)。
这个修正是受欢迎的:从 C23 开始,malloc(1) 不再有对齐要求,并且连续调用 malloc(1) 可能会返回一个字节包装数组中连续的地址。同样,malloc(2) 不再需要适当对齐以适应大于 2 的大小的对象。malloc(3) 将适当对齐于大多数架构上的 2 字节对象,例如 short 等。
这可能会对利用原始对齐要求在
malloc()
返回的对象指针的低位存储标签的包造成问题。在这种系统上,传递给
malloc
的大小必须大于或等于
2n,其中
n是标签中的位数,通常限制为3或4。更好的解决方案是使用
aligned_malloc()
,可以指定和测试对齐要求。
还要注意,
calloc(4, 1)
返回的块的对齐要求为4,因为
分配的大小是参数的乘积,第一个参数是要为其分配空间的元素数量,第二个参数是元素大小。因此,程序员不需要了解参数的精确语义。请注意,在其他接受这些参数的C库函数(如
fread()
、
fwrite()
、
qsort()
和
bsearch()
)中,
nelems
和
size
的顺序不同。
realloc()
遵循相同的要求:减小块的大小可能会产生具有较弱对齐的不同指针。
calloc(a,b)
和“小于或等于所请求的_size_”,在我看来,_size_是a*b
,如果需要可以使用扩展数学。 - chux - Reinstate Monicacalloc(a, b)
和 "小于或等于所请求的 size",在我看来,size 是a*b
,如果需要使用扩展数学。 - chux - Reinstate Monica