You should also ditch the realloc() in pop. You need not size down your array since when you "push" it, you are going to re-increment it. But realloc doesn't always necessarily allocate nor deallocate physical space. You do not necessarily know with any predictable certainty when malloc() has already over-allocated (which it typically does in order to preserve alignment anyway).

As you can see, there is a memcpy for every growth of the memory - which can take some significant time if the size is large.

[A real realloc is a bit more complex than that, but for illustration purposes, I kept it really simple - but most of the time, realloc doesn't genuinely shrink the memory unless it's a HUGE amount smaller].

An optimized approach may be to grow the size by doubling it [or adding half again, a quarter or four times - benchmarking a few differnet variants and comparing performance and memory usage will tell you what's the best version]. Of course, this means that you have to have two variables - one to keep track of the size of the vector space, and one to keep track of how much of the space is actually used. But it will make it many times faster for large sizes.