A good C equivalent of STL vector?

Viewed 15304

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?

7 Answers

Personally, I prefer "Gena" library. It closely resembles stl::vector in pure C89.

It is comfortable to use because you can:

  • Access vector elements just like plain C arrays: vec[k][j];
  • Have multi-dimentional arrays;
  • Copy vectors;
  • Instantiate necessary vector types once in a separate module, instead of doing this every time you needed a vector;
  • You can choose how to pass values into a vector and how to return them from it: by value or by pointer.

You can check it out here:

https://github.com/cher-nov/Gena

Related