I have heard that a successful call to malloc()
returns a pointer suitably aligned for any type. Yet it seems useless and wasteful to require malloc(1)
to return a pointer aligned for a larger value than 1
since no object larger than char
can be stored into the block.
What is the alignment requirement for malloc(1)
, malloc(2)
, etc.
If the alignment is larger than the allocated size, what is the rationale for such a requirement?
The definition of the
malloc
function in the C Standard is terse and does not specify anything regarding alignment. The abstract from the C23 Standard below is substantially similar to previous editions with only a chapter number change:Regarding the block alignment requirement, up until C17, this was specified at the beginning of the parent chapter:
This meant that
malloc(1)
must be correctly aligned for all fundamental types such asint
,long
,long long
, etc. and is somewhat ambiguous about accessing such objects in the space allocated.Reported as a defect, this problem was discussed and the text was amended in C23 to relax this requirement and clarify this ambiguity (emphasis mine):
This amendment is welcome: from C23 on,
malloc(1)
has no alignment requirement and successive calls tomalloc(1)
may return successive addresses in a packed array of bytes. Similarly,malloc(2)
is no longer required be be suitably aligned for objects of size greater than 2.malloc(3)
will be suitably aligned for 2 byte objects such asshort
on most architectures, etc.This may cause problems for packages that take advantage of the original alignment requirement to store tags in the low order bits of object pointers returned by
malloc()
. The size passed tomalloc
on such systems must be greater than or equal to 2n where n is the number of bits in the tag, typically limited to 3 or 4. A better solution is to usealigned_malloc()
where the alignment requirement can be specified and tested.Note also that the alignment requirement for the block returned by
calloc(4, 1)
is 4, as the allocated size is the product of the arguments, the first being the number of elements to allocate space for, the second being the element size. Programmers hence do not need to be aware of the arguments' precise semantics. Note thatnelems
andsize
are passed in a different order in other C library functions that take such arguments, such asfread()
,fwrite()
,qsort()
andbsearch()
.realloc()
follows the same requirements: reducing the size of a block may produce a different pointer with a weaker alignment.