The following header shows a way to make a generic dynamic array in C with an array of two pointers:
the first pointer stores the length of the dynamic array;
the second pointer points to the data.
So, int *vec[2] = { 0 }; is an empty dynamic array of ints. struct person *people[2] = { 0 }; is an empty dynamic array of people.
(uintptr_t)vec[0] is the length of the array, vec[1] is the array.
The vec_push macro pushes a value at the end of the dynamic array and returns true on success.
This code is C23 with statement expressions (a GNU C feature).
Why is this interesting
First of all, structs aren't used so you don't have to invent names for them (e.g. there is no IntVec ). Since a pointer is used to store the length of the dynamic array (as a uintptr_t ), this relies on implementation-defined behavior, that is the uintptr_t length read from a pointer must be the same length that was stored.
Second of all, capacity isn't stored at all.…