A good C equivalent of STL vector?

c c89
Christoffer picture Christoffer · Aug 11, 2010 · Viewed 11.8k times · Source

I've noticed that at several places in our code base we use dynamically expanding arrays, i.e. a base array coupled with an element counter and a "max elements" value.

What I want to do is replace these with a common data structure and utility functions, for the usual object-oriented reasons. The array elements can be either basic data types or structs, I need fast random access to the elements, and preferably a type-safe implementation.

So, basically, what I would like to use is an STL vector, but the code base is restricted to C89 so I have to come up with something else :-)

I gave it some thought and whipped up this initial draft, just to show what I'm aiming at:

/* Type-safe dynamic list in C89 */

#define list_declare(type) typedef struct _##type##_list_t { type * base_array; size_t elements; size_t max_size; } type##_list_t
#define list(type) type##_list_t
#define list_new(type, initial_size) { calloc(initial_size, sizeof(type)), 0, initial_size }
#define list_free(list) free(list.base_array)
#define list_set(list, place, element) if ( list.elements < list.max_size ) { list.base_array[place] = element; } else { /* Array index out of bounds */ }
#define list_add(list, element) if ( list.elements < list.max_size ) { list.base_array[list.elements++] = element; } else { /* Expand array then add */ }
#define list_get(list, n) list.base_array[n]

/* Sample usage: */

list_declare(int);

int main(void)
{
    list(int) integers = list_new(int, 10);
    printf("list[0] = %d\n", list_get(integers, 0));
    list_add(integers, 4);
    printf("list[0] = %d\n", list_get(integers, 0));
    list_set(integers, 0, 3);
    printf("list[0] = %d\n", list_get(integers, 0));
    list_free(integers);

    return EXIT_SUCCESS;
}

...however, there must be someone else who has done this before. I'm aware of the FreeBSD sys/queue.h implementation of a similar concept for some different queues, but I can't find anything like that for arrays.

Is anyone here any wiser?

Answer

lunaryorn picture lunaryorn · Aug 11, 2010

glib provides an GArray type, which implements a dynamically growing array. If you can use external 3rd party libraries, glib is almost always a good choice as "standard" library for C. It provides types for all basic data structures, for unicode strings, for date and time values, and so on.