The RAII benefits are definitely there and STL containers are pretty awesome, but you can still create generic containers in C by using void pointers. For example, a simple vector API:
typedef struct { void *elements; int elem_size; int n; } Vector;
Vector *vector_new(int elem_size);
void vector_free(Vector *v);
void vector_push(Vector *v, void *elem);
void vector_pop(Vector *v);
int vector_size(Vector *v);
void *vector_at(Vector *v, int i);
etc. This is off the top of my head, but you get the idea. You can basically put anything you want in there as long as you say how large the elements are upon initialization.
The problem with using void* pointers is that every access to an element costs one extra dereference operation. By using C++ templates, the compiler can create object code specifically compiled for each data type, without the need for pointers. (On the other hand, this can make C++ binaries much larger).
In this case, I'm not storing void pointers in the data structure, but I'm using the void pointer as a direct address into "elements". The memory layout is just a sequence of items of length elem_size. vector_push copies the item into that memory (and doubles the size of "elements" with realloc when necessary).
So you have a memcpy() call in vector_push? I wonder if that's less efficient than a straight-up assignment for small objects such as integers. The C++ equivalent can be further optimized during instruction generation by keeping things in the CPU registers as long as possible. In your C case, the int has to be written to memory before memcpy can load it into its buffer.
There is a good book on generic C programming: http://sites.google.com/site/cinterfacesimplementations/