My own malloc() function in C Is this acceptable? What is the next step to improve algorithm and make them more clear and faster?

typedef struct heap_block
{  
    struct heap_block* next;
    size_t size;
    bool isfree;
    int x; // for alligment
}header;

#define Heap_Capacity 16777216
unsigned long long active_size;  // # bytes in active allocations

static uint64_t heap[Heap_Capacity/sizeof(uint64_t)];

static char* max_heap =(char*)(&amp;heap[0]);
static char* min_heap = (char*)(&amp;heap[0]);
static char *END_CHK = "\xDE\xAD\xC0\xDA";
header* last_allocated;

void* malloc(size_t sz) 
{
    if(sz == 0 || sz &gt; Heap_Capacity)
    {
        return NULL;
    }

    header* block = (header*)heap;
    if(active_size == 0)
    {
        set_data_to_block(block, sz);
        return (void*)last_allocated;
    }

    while(block-&gt;next != NULL)
    {
        block = block-&gt;next;
    }

    block-&gt;next = (header*)((char*)to_end_data(block) + 8);
    header* new_block = block-&gt;next;
    set_data_to_block(new_block, sz);

    return (void*)last_allocated;
}


void set_data_to_block(header* block, size_t sz)
{
    block-&gt;size = sz;
    block-&gt;isfree = false;
    block-&gt;next = NULL;

    active_size += sz;
    last_allocated = block + 1;
    char* end_of_data_block = (char*)to_end_data(block);

    if(max_heap &lt; end_of_data_block)
    {
        max_heap = end_of_data_block;
    }
    strcpy(end_of_data_block, END_CHK);
}

header* to_start_metadata(header* block)
{
    return --block;
}

header* to_end_data(header* block)
{
    return (header*)((size_t)(block+1) + block-&gt;size);
}
Avoid globals

last_allocated is only used to communicate the result of set_data_to_block back to malloc. Returning the result is much cleaner.
Avoid special cases

There is no need to special case the initial allocation. If you do not want to rely on ((header *) heap)-&gt;next == NULL initially, you may want to provide an initialization method (which I recommend anyway).