std::vector does indeed have at least one pointer member (otherwise you couldn't have a std::vector with automatic storage duration because the size would be unknowable) so there is some indirection. Maybe you're thinking of std::array?
Array array_create(size_t size, size_t sizeof_data) {
Array result;
result.size = size;
result.capacity = size;
if(size) {
result.data = malloc(size * sizeof_data);
} else {
result.data = NULL;
}
return result;
}In ARRAY_PUSH_BACK, it just inserts the element directly into the buffer, provided there is enough capacity. There is no separate allocation for an element.
You don't need to redefine the struct for each element type, since the macro casts 'data' (type void *) to whatever the array's type is.