A void *
представляет собой сложную задачу в связанном списке, так как вам приходится управлять его размещением отдельно для самого списка. Один из подходов, которые я использовал в прошлом, - это иметь структуру с переменным размером, такую как:
typedef struct _tNode {
struct _tNode *prev;
struct _tNode *next;
int payloadType;
char payload[1]; // or use different type for alignment.
} tNode;
Теперь я понимаю, что не выглядит переменного размера, но давайте выделим структуру таким образом:
typedef struct {
char Name[30];
char Addr[50];
} tPerson;
tNode *node = malloc (sizeof (tNode) - 1 + sizeof (tPerson));
Теперь у вас есть узел, который для всех намерений и целей выглядит следующим образом:
typedef struct _tNode {
struct _tNode *prev;
struct _tNode *next;
int payloadType;
char Name[30];
char Addr[50];
} tNode;
или в графическом виде (где [n]
означает n
байт):
+----------------+
| prev[4] |
+----------------+
| next[4] |
+----------------+
| payloadType[4] |
+----------------+ +----------+
| payload[1] | <- overlap -> | Name[30] |
+----------------+ +----------+
| Addr[50] |
+----------+
То есть, если вы знаете, как правильно обращаться с полезной нагрузкой. Это можно сделать следующим образом:
node->prev = NULL;
node->next = NULL;
node->payloadType = PLTYP_PERSON;
tPerson *person = &(node->payload); // cast for easy changes to payload.
strcpy (person->Name, "Bob Smith");
strcpy (person->Addr, "7 Station St");
Эта строка приведения просто преобразует адрес символа payload
(в типе tNode
) в адрес фактического tPerson
типа полезной нагрузки.
Используя этот метод, вы можете переносить любой тип полезной нагрузки в узле, даже различные типы полезной нагрузки в каждом узле , без потери пространства объединения. Эта потеря может быть замечена со следующим:
union {
int x;
char y[100];
} u;
где 96 байтов тратятся впустую каждый раз, когда вы сохраняете целочисленный тип в списке (для 4-байтового целого).
Тип полезной нагрузки в tNode
позволяет вам легко определить, какой тип полезной нагрузки несет этот узел, поэтому ваш код может решить, как его обработать. Вы можете использовать что-то вроде:
#define PAYLOAD_UNKNOWN 0
#define PAYLOAD_MANAGER 1
#define PAYLOAD_EMPLOYEE 2
#define PAYLOAD_CONTRACTOR 3
или (возможно, лучше):
typedef enum {
PAYLOAD_UNKNOWN,
PAYLOAD_MANAGER,
PAYLOAD_EMPLOYEE,
PAYLOAD_CONTRACTOR
} tPayLoad;