Eu criei um alocador de arena muito simples em C e fiquei pensando em uma coisa.
Aqui está meu arquivo de cabeçalho (a propósito, se esta API não parecer correta, por favor me avise!).
#ifndef ARENA_H
#define ARENA_H
#include <stddef.h>
struct Arena;
/* Returns a new arena allocator with a capacity of SIZE */
struct Arena *arena_new(size_t size);
/* Allocates SIZE bytes of memory from ARENA aligned with a default alignment
set to `__alignof__(max_align_t)`. */
void *arena_alloc(struct Arena *arena, size_t size);
/* Allocates SIZE bytes of memory from ARENA with no alignment */
void *arena_alloc_packed(struct Arena *arena, size_t size);
/* Allocates SIZE bytes of memory from ARENA aligned on ALIGN. */
void *arena_alloc_align(struct Arena *arena, size_t size, size_t align);
/* Free all memory allocated with ARENA */
void arena_free(struct Arena *arena);
#endif /* ARENA_H */
Na implementação, arena_alloc_align
costumo uintptr_t
converter o endereço do ponteiro do bloco de memória para um tipo com o qual posso calcular o alinhamento do endereço.
void *arena_alloc_align(struct Arena *arena, size_t size, size_t align)
{
assert((align & 1) == 0 && "aligment must be a power of two");
uintptr_t curr_addr = (uintptr_t)arena->mem_block + arena->cursor;
size_t padding = 0;
if (align > 0 && !IS_ALIGNED(curr_addr, align))
padding = align - (curr_addr & (align - 1));
if(arena->cursor + padding + size > arena->capacity)
return NULL;
arena->cursor = padding + size;
return (void *)curr_addr + padding;
}
Esse tipo ( uintptr_t
) é ok para usar? Tipo, ele é portátil? Porque pelo que eu li, esse tipo é opcional , isso significa que em alguma implementação de compilador ele pode não ser implementado?
Se sim, que tipo posso usar para converter um ponteiro para um tipo que seja grande o suficiente para conter qualquer endereço de memória?
Encontrei algumas outras perguntas relacionadas, mas as pessoas não parecem dar uma alternativa que seja definida no padrão e que não seja opcional. (Posso ter perdido a resposta que estava procurando).