Я заметил, что в нескольких местах нашей базы кода мы используем динамически расширяющиеся массивы, т. Е. Базовую матрицу, связанную с счетчиком элементов и значением «максимальных элементов».Хороший C-эквивалент STL-вектора?
Что я хочу сделать, это заменить их общей структурой данных и функциями полезности для обычных объектно-ориентированных причин. Элементы массива могут быть либо базовыми типами данных, либо структурами, мне нужен быстрый случайный доступ к элементам и, предпочтительно, реализация типа безопасная.
Так, в основном, то, что я хотел бы использовать это вектор STL, но базовый код ограничен C89, поэтому я должен придумать что-то другое :-)
Я дал ему некоторые мысли и взбитые до этого первоначального проекта, просто чтобы показать, что я стремлюсь на:
/* 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;
}
... однако, должен быть кто-то, кто сделал это раньше. Я знаю о реализации FreeBSD sys/queue.h аналогичной концепции для некоторых разных очередей, но я не могу найти ничего подобного для массивов.
Кто-нибудь здесь мудрее?
По крайней мере, либо избавиться от макросов и заменить их функциями, или установить их так, чтобы они работали как функции. Последнее включает в себя обертывание любого макроса, который является более чем одним выражением/выражением с помощью 'do {...} while (0)'. –
Почему я хочу избавиться от макросов? Замена их функциями могла бы победить независимость типа, это уже не было бы общим решением. Кроме того, почему я хочу обернуть с помощью do ... while? Это сделало бы невозможным возврат значений из макропоследовательностей. – Christoffer
@christoffer: перечитайте комментарий R. Обратите внимание на использование «или» - эти макросы функций ужасны, вы должны улучшить их, «исправляя» их, как говорит R. Это делает использование макроса функции менее неожиданным. Я бы предпочел, чтобы макросы функций были заглавные, для хорошей оценки. – Arafangion