1

我有一个数据结构,链表,看起来像

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 中复制这种风格,考虑到它可能不一定合乎逻辑?

4

2 回答 2

0

在第一种情况下,您将指针 (ll) 的副本压入堆栈。您的代码分配内存,我认为sizeof(slinkedlist)是拼写错误,用 0 填充它,....然后丢弃副本。你的调用者永远不会得到更新的指针。打印ll初始化后的值。在第二个中,您将一个指针推送到该指针,该指针被分配/初始化,当您返回时,您的调用者可以愉快地使用它。如果不是返回 0 或 1,而是返回ll并将返回值分配给调用者中的变量,则可以使用第一个版本。那将是一种功能风格。

于 2013-07-21T15:30:44.913 回答
0

在第一个版本中,您所做的是分配一块新的内存,将其归零,然后将其复制到list参数中(这不会改变ll,因为 C 通过值发送参数)。第二个版本有*list,其中 list 是指向 的指针ll,这意味着当您更改时,*list您实际上会更改ll(与第一个版本不同)。

于 2013-07-21T15:18:37.603 回答