mrjbom
@mrjbom

Реализация двусвязного списка с элементами конкретного типа?

Привет.
Я пишу реализацию двусвязного списка и у меня возникли проблемы с добавлением туда элементов...
Сам элемент выглядит так:
typedef struct list_item {
	struct list_item* next; //указатель на следующий элемент
	struct list_item* prev; //указатель на предыдущий элемент
	void* data_ptr; //указатель на данные
	size_t data_size; //размер данных
} list_item_t;


А вот функция которая добавляет новый элемент с данными:
void list_add_data(list_t* list, void* data, size_t data_size);


Проблема в том, что я не могу добавить туда к примеру число 10 и 12, для этого мне нужно делать что-то в стиле
int num = 10;
int num2 = 12;
list_add_data(&list, &num, sizeof(int));
list_add_data(&list, &num2, sizeof(int));

или
int* num = malloc(sizeof(int));
*int = 10;
list_add_data(&list, num, sizeof(int));
num = malloc(sizeof(int));
*int = 12;
list_add_data(&list, num, sizeof(int));

А если нужно добавить несколько значений, то под каждое значение нужно создавать отдельную переменную или выделять память и следить за ней. Очевидно что получается плохо.

Я бы мог сделать отдельную функцию под все типы, типа void list_add_int(list_t* list, int data); которая будет выделять память под число и сохранять ссылку, но в этом случае под каждый возможный тип я должен создавать отдельный экземпляр функции, это тоже не решение.

Могу ли я сделать что-то похожее на типы данных в C++?
Что-то похожее на vector<int> vec; и простых функций которые будут работать с элементами того типа, который требуется.
  • Вопрос задан
  • 101 просмотр
Пригласить эксперта
Ответы на вопрос 1
wataru
@wataru
Разработчик на С++, экс-олимпиадник.
К сожалению, в C не завезли шаблоны. И, если вы хотите хранить разные типы в одном списке или использовать один код для реализации списков разных типов, то придется работать с указателями, а значит выделать память где-то придется.

Можно в функции добавления элемента принимать указатель и размер, выделять новую память и копировать.
Это что-то вроде вашего предложения, но работает для всех типов.

Можно 2 функции сделать для оптимизации: одна будет копировать и вызываться должна для локальных переменных, а вторая не будет копировать, а будет брать ответственность за переданный указатель. Но тут можно легко ошибиться - при вызове второй функции надо переданный указатель сразу забыть. Иначе можно его 2 раза потом удалить, или использовать после удаления.

Если же вы собираетесь только инты хранить - то лучше переписать список: храните не указатель на data, а сразу int.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы