Another dynamic array implementation in C I saw quite a few posts about making a dynamic array so I tried making my own for learning purposes.
Here it is:
#ifndef VECTOR_H
#define VECTOR_H

#include &lt;stdlib.h&gt;
#include &lt;stdbool.h&gt;
#include &lt;string.h&gt;

#ifndef VECTOR_RESERVE_SIZE 
#define VECTOR_RESERVE_SIZE 4
#endif

//Declaration

typedef struct
{
        int size_of_each;
        int reserved;
        int used;
        void* data;
} vector_t;

bool vector_init(vector_t *, int);
void vector_append(vector_t *, void *);
void* vector_get(vector_t *, int );
void vector_set(vector_t *, int, void *);
void vector_free(vector_t *);

//Implementation

bool vector_init(vector_t *p, int s)
{
        p-&gt;size_of_each = s;
        p-&gt;reserved = VECTOR_RESERVE_SIZE;
        p-&gt;used = 0;
        p-&gt;data = malloc(VECTOR_RESERVE_SIZE * p-&gt;size_of_each);

        if (p-&gt;data != NULL) { return false; }
        else { return true; }
}

void vector_append(vector_t *p, void *d)
{
        if (p-&gt;used == p-&gt;reserved)
        {
                p-&gt;data = realloc(p-&gt;data, VECTOR_RESERVE_SIZE);
                //printf(&quot;reallocated \n&quot;);
                p-&gt;reserved += VECTOR_RESERVE_SIZE;
        }
        memcpy((void*)((char*)p-&gt;data + p-&gt;size_of_each * p-&gt;used),  // copy to back of the vector
                        d, p-&gt;size_of_each);

        p-&gt;used += 1;
}

void* vector_get(vector_t *p, int i)
{
        if (!(i &gt; p-&gt;used))
        {
                return (void*)((char*)p-&gt;data + p-&gt;size_of_each * i);
        }
        else { return NULL; }
}

void vector_set(vector_t *p, int i, void *d)
{
        if (!(i &gt; p-&gt;used))
        {
                memcpy((void*)((char*)p-&gt;data + p-&gt;size_of_each * i), d, p-&gt;size_of_each);
        }
}

void vector_free(vector_t *p)
{
        free(p-&gt;data);
}

#endif

Here is an example of its usage:
#include &lt;stdio.h&gt;

#define VECTOR_RESERVE_SIZE 3
#include &quot;vector.h&quot;

int main()
{
        int a = 321;
        int b = 45;
        int c = 21;
        int d = 31;
        int e = 71;

        vector_t v;
        vector_init(&amp;v, sizeof (int));

        vector_append(&amp;v, &amp;a);
        vector_append(&amp;v, &amp;b);
        vector_append(&amp;v, &amp;c);
        vector_append(&amp;v, &amp;d);
        vector_append(&amp;v, &amp;e);

        printf(&quot;1st element is  %d \n&quot;, *(int*)vector_get(&amp;v, 0));
        printf(&quot;2nd element is  %d \n&quot;, *(int*)vector_get(&amp;v, 1));
        printf(&quot;3th element is  %d \n&quot;, *(int*)vector_get(&amp;v, 2));
        printf(&quot;4th element is  %d \n&quot;, *(int*)vector_get(&amp;v, 3));
        printf(&quot;5th element is  %d \n\n&quot;, *(int*)vector_get(&amp;v, 4));

        vector_set(&amp;v, 4, &amp;a);
        printf(&quot;4th element after setting is  %d \n\n&quot;, *(int*)vector_get(&amp;v, 4));

        //contiguous
        printf(&quot;size of int is: %d \n&quot;, sizeof (int));
        printf(&quot;address of 1st element: %p \n&quot;, vector_get(&amp;v, 0));
        printf(&quot;address of 2nd element: %p \n&quot;, vector_get(&amp;v, 1));
        printf(&quot;address of 3rd element: %p \n&quot;, vector_get(&amp;v, 2));
        printf(&quot;address of 4th element: %p \n&quot;, vector_get(&amp;v, 3));
        printf(&quot;address of 5th element: %p \n&quot;, vector_get(&amp;v, 4));

        vector_free(&amp;v);
}


I've written some C++ before and this was one of my first few projects in C.
I'd like to know overall how good my code is and whether I'm using good practices / conventions.
Edit:
this:
p-&gt;data = realloc(p-&gt;data, VECTOR_RESERVE_SIZE);
should be this:
p-&gt;data = realloc(p-&gt;data, (p-&gt;reserved  + VECTOR_RSERVE_SIZE) * P-&gt;size_of_each); 
Edit: Maybe it's too late but, if people are still reviewing this I would really like to know how does this approach compare to std::vector.
In C, as in C++, object pointers can be freely converted to void*, so quite a few casts can be removed.
It's probably convenient to store data as a char*, since that's how we use it.  We should still use void* as external interface, of course.
This is a dangerous anti-pattern:

            p-&gt;data = realloc(p-&gt;data, VECTOR_RESERVE_SIZE);


If the realloc() fails, it returns a null pointer.  By overwriting p-&gt;data before we check for null, we leak the old value of p-&gt;data, which is no longer accessible.  And the null-check is also missing, so subsequent access is Undefined Behaviour.
Style-wise, I think I'd find (!(i &gt; p-&gt;used)) easier to read as (i &lt;= p-&gt;used).  And if (p-&gt;data != NULL) { return false; } else { return true; } as return !p-&gt;data;.
The example code should set a good example, and check the return value of vector_init() (and also vector_append() once you realise it needs to indicate success/failure) and react appropriately.  Otherwise, you'll find you're encouraging slapdash usage.