[第一次问一个问题,但我确实环顾了Google和stackoverflow,看看以前是否有人问过类似的问题。例如,在malloc, recasting and free中,OP要求类似的内容。但这更复杂。
我想知道是否有可能在C中为遍历列表的列表结构创建一个通用函数,因为您知道不同类型的结构将始终具有“下一个”字段。
例如,给定这两个列表类型的结构:
typedef struct _list1 {
int value;
list1 *next;
} list1;
typedef struct _list2 {
int value;
char *string;
list2 *next;
} list2;
是否可以创建通用的void freeList((void) *list)
函数或类似于以下内容的函数?我知道为每个单独的列表分别编写两个免费函数是一件容易的事。
void freeList((void) *list) {
// Included this because the structs would have different sizes
// so I thought it would be possible to cast it in order to properly dereference the field.
if (sizeof *list == sizeof list1)
*list = (list1) list;
else if (sizeof *list == sizeof list2)
*list = (list2) list;
if (!list) return;
else {
free(list->next);
free(list);
}
}
到目前为止,鉴于gcc会抱怨取消引用void *
指针,因此我对上述代码的实验效果不佳。
制作异构列表可以通过使用标记的联合,或者仅使用标记和强制转换来实现:
struct list_item {
struct list_item *next;
enum type;
void *contents;
}
或
struct list_item {
struct list_item *next;
enum datatype type;
union {
int some_int;
char some_char;
} contents;
}
然后遍历列表时,您只需要在使用元素的内容之前验证type
中存储的类型。
此支票:
if (sizeof *list == sizeof list1)
*list = (list1) list;
else if (sizeof *list == sizeof list2)
*list = (list2) list;
无效,因为sizeof
是静态构造:其值在编译时定义。您只需要输入sizeof void
。
如果确保下一个指针是该结构的第一个成员,则可以这样做。
typedef struct list1 {
// next pointer must be first
struct list1 *next;
int value;
} list1;
typedef struct list2 {
// next pointer must be first
struct list2 *next;
int value;
char *string;
} list2;
void freeList(void *list) {
if (list) {
freeList(*(void**)list);
free(list);
}
}