In C99, is it possible to write a well-defined program which
implements its own memory allocation in an alignment-responsible way,
without using the C99 memory management functions?
For example, out of some pool with 'static' storage duration? I
cannot figure out how in any pool of 'unsigned char[XXX]', we could
determine the alignment for where a pointer might point to.
enum
{
POOL_SIZE = 1024 /* Allow 1 KB to be allocated */
};
static char pool[POOL_SIZE];
static size_t pool_used = 0;
void *pool_alloc(size_t bytes, unsigned int align_log2)
{
char *block;
size_t alignment;
/* Get pointer to free space */
block = pool + pool_used;
/* Align pointer to nearest equal or higher multiple
of 2 to the power of align_log2. */
alignment = 1 << align_log2;
block = (block + (alignment - 1)) & ~(alignment - 1);
/* Is there enough free space for the allocation? */
if (POOL_SIZE - (block - pool) < bytes)
{
block = NULL; /* Not enough free space */
}
else
{
pool_used = (block - pool) + bytes;
}
return block;
}
A C compiler can't optimise multiplication and division by the
required alignment granularity (here, 2 to the power of 'align_log2')
unless it is a known constant. That is why my function uses bitwise
operators instead of integer multiplication and division. Because the
bitwise method only works for powers of two, I require the caller to
specify the alignment in that form.
Of course, if you need alignment to some multiple of a value that
isn't a power of two then it gets more computationally expensive.
If you're writing a macro rather than a function then you could
instead use ((((block) + ((alignment) - 1)) / (alignment)) *
(alignment)), which has the advantage of being more obvious and
working for all positive values of 'alignment'.
My function wastes less memory than the typical case of calling
malloc() and then aligning a pointer within the allocated block. In
that case, you have to include the maximum possible wastage in the
amount of memory requested. By the time you find out that you can
align to the required granularity and still have bytes free at the end
of the block, it is too late to do anything about it.
All untested and off the top of my head.