hugomg
hugomg

Reputation: 69934

In C, how can I get the appropriate memory alignment for my platform?

I am writing a custom arena allocator, which allocates blocks of varying sizes from a large buffer. However, I want to ensure that the addresses returned by it are always appropriately aligned, similarly to how malloc always returns suitably-aligned pointers.

#define ALIGN 16

char buffer[2048];
char *next = buffer;

// Allocates a block of memory, ensuring that "next"
// is always a multiple of ALIGN.
void *alloc(size_t nbytes)
{
    void *ret = next;
    next += (nbytes + ALIGN - 1) & ~(ALIGN - 1);
    return ret;
}

int main()
{
    void *p1 = alloc(1);
    void *p2 = alloc(5);
    void *p3 = alloc(17);
    // ...
}

Is there a way to find out what is the appropriate memory alignment that I should use for the platform my code is being compiled for? Or should I just set ALIGN to a large enough constant, as I do in the code example?

Upvotes: 2

Views: 457

Answers (1)

KamilCuk
KamilCuk

Reputation: 140950

Is there a way to find out what is the appropriate memory alignment that I should use

If it's going to be simple obstack implementation, you could pass the type alignment requirements to your alloc function, thus possibly reducing memory usage.

#include <stdalign.h> // from C11

void *super_alloc(size_t alignment, size_t size, size_t count);

int *five_ints = super_alloc(alingof(int), sizeof(int), 5);

#define SUPER_ALLOC(type, count)  \
       ((TYPE*)super_alloc(alignof(TYPE), sizeof(TYPE), (count)))
double *seven_doubles = SUPER_ALLOC(double, 7);

Before C11 you may write compiler specific code along #define alignof(type) compiler_specific_code_here(type). There are aligned_alloc and posix_memalign.

for the platform my code is being compiled for?

When you know the platform, then you know it. Research the documentation of that specific platform you are compiling for and find out it's maximum required alignment for any types.

In C11 there is max_align_t that you could use and it should be set by your compiler:

static const size_t ALIGN = alignof(max_align_t);

You could potentially take all types and write a big MAX(alignof(int), alignof(long int), alignof(double), alignof(long double) function-switch with all the types.

Or should I just set ALIGN to a large enough constant, as I do in the code example?

That said, 16 is going to be most probably definitely enough for 99,9% platforms out there, but feel like a waste on platforms with smaller alignment requirements.

Upvotes: 3

Related Questions