我有一个数据结构,链表,看起来像
struct listitem {
void* data;
struct listitem* next;
};
typedef struct listitem listitem;
typedef struct {
listitem* head;
pthread_rwlock_t lock;
} linkedlist;
我正在为数据使用指向 void* 的指针,因为我想使数据结构具有多态性,以便可以将它用于一些不同的应用程序。
为了初始化列表(分配内存并初始化 rw 锁),我将它传递给函数 init_list(..)。当我按如下方式传递指向列表的指针时,每当我尝试对列表执行任何进一步操作(例如,将项目推送到它)时,程序都会挂起:
int init_list(linkedlist* list /* borrowed - list to initialise (probably unallocated) */) {
list = (linkedlist*)calloc(1, sizeof(linkedlist)); // clear the memory, so that head is a null pointer
printf("Allocated memory\n");
if (list == 0) {
perror("calloc failed on allocating memory for list");
return 1;
}
printf("Initialising lock\n");
pthread_rwlock_init(&list->lock, NULL);
return 0;
}
...
linkedlist* ll;
init_list(ll);
我的理解是上面应该清除ll指向的内存并适当地初始化锁的内存位置。
但是,当我将指针传递给指向列表的指针时,一切正常(即,当我尝试执行进一步的操作(如获取锁并将项目推送到列表)时,程序不会挂起)。我不明白为什么添加这个额外的间接层使它起作用。我会认为实际内存位置上的操作是相同的,不管我如何引用它们?
即以下工作,而第一种方法没有:
int init_list(linkedlist** list /* borrowed - list to initialise (probably unallocated) */) {
*list = (linkedlist*)calloc(1, sizeof(linkedlist)); // clear the memory, so that head is a null pointer
printf("Allocated memory\n");
if (list == 0) {
perror("calloc failed on allocating memory for list");
return 1;
}
printf("Initialising lock\n");
pthread_rwlock_init(&(*list)->lock, NULL);
return 0;
}
...
linkedlist* ll;
init_list(&ll);
我无法解释为什么第二种方法有效而第一种方法无效。
就一般风格而言,这种做法是否普遍?还是有更好、更通用的 C 语言初始化数据结构的方法?我是一个相对较新的 C 程序员,来自面向对象的语言,我希望在构造函数中进行这样的初始化,我有点试图在 C 中复制这种风格,考虑到它可能不一定合乎逻辑?