> Are you really going to recommend growing the table by duplicating it?
Um... yes.
You want the data linearly in memory in the first place so you can have constant time access by index. If you want to grow a dynamic array, doing a realloc can easily cause the same effect as the article does manually (alloc new, copy data, free old), because the memory immediately after may be occupied by something else if you did any other malloc/calloc. Copying over the data is linear in time, thus degrading your constant time insert to linear time as soon as the table is full if you do a realloc for single items instead.
You may find the choice of growing when half full as in the article questionable, because then there will always be an unused half, but pretty much every, remotely practical dynamic array implementation in C (and probably a ton of other languages) does that (grow by capacity * 2 when full) to maintain amortized constant time when appending.