我正在读'学习C艰难之路'。这里一个函数List *List_create()
有一个返回类型List,我理解但是我不知道*List_create()
真的有用吗?这是什么功能?
struct ListNode; //I also don't know what this does
typedef struct ListNode{
struct ListNode * next;
struct ListNode * prev;
void *value;
}ListNode;
typedef struct List{
int count;
ListNode *first;
ListNode *last;
}List;
List *List_create()
{
return calloc(1,sizeof(List));
}
答案 0 :(得分:0)
该函数在动态内存中创建一个类型为List
的对象的实例,用零初始化该对象的所有成员并返回指向该对象的指针。
实际上,不需要在动态内存中创建列表。 你也可以写
List list = { 0 };
不同之处在于,在第一种情况下,您将需要删除不再需要的动态分配列表。
在第二种情况下,编译器会费心删除列表对象。
但是在这两种情况下,您必须自己删除列表中的节点。因此,您需要编写一个函数,为列表中已分配的节点释放所有已分配的内存。
答案 1 :(得分:0)
List_create
为列表结构分配内存,用于双向链表并初始化该结构。 struct需要有第一个和最后一个的空指针,以及0的count。此函数滥用了大多数平台上空指针的值为0的事实。而calloc
只是将它分配的内存设置为0。
答案 2 :(得分:0)
嗯,这段代码中至少有一个基本错误,这让我想知道这是否是一个很好的学习来源。
返回类型为List*
,而不是List
。这是一个指向List类型的指针,这意味着它将一直存在,直到你释放它(通过调用free
)。 calloc分配这样的内存并将其设置为全零,这是初始化结构的常用方法。
代码中的错误在函数声明符中,List_create()
在现代C中不合适,它应该是List_create(void)
。也许它只是一个错字,或者作者可能更习惯于C ++,但它仍然是错误的。但是它仍然是一个错误。
*
放在函数名旁边而不是List
旁边的原因是当你声明指针变量时,*
附加到名称而不是类型
E.g。 List *foo, bar;
声明了两个变量。 foo
是指向List
的指针,而bar
不是指针。如果它写成List* foo, bar;
(意思相同但对阅读代码的人来说很困惑),这就不那么清楚了。
答案 3 :(得分:0)
在C中,有两种方法可以处理结构:
按值,其中没有指针。在这种情况下,将结构传递给函数,或者从函数返回一个函数,需要按字节逐个复制整个结构。这适用于小结构,但对大结构效率低。
通过引用,在其中使用malloc
或calloc
来“动态”分配将保存结构数据的一块内存,然后通过指针。
您的List_create函数选择使用按引用模型。这可能是正确的选择,因为它确保列表的所有持有者始终可以看到对列表的更新。
如果它选择了 by value 模型,那么您必须始终确保在List结构的本地副本中拥有最新的更新。即List_add
必须传回修改后的列表,这样不方便且容易出错。
示例:引用:
List *List_create()
{
return calloc(1,sizeof(List));
}
void List_add(List* list, void *value) {
/* TODO: actual insert code */
}
void example_caller() {
List *list = List_create();
List_add(list, whatever);
}
示例:按值:
List List_create()
{
List result = {0};
return result;
}
List List_add(List list, void *value) {
/* TODO: actual insert code */
return list;
}
void example_caller() {
List list = List_create();
list = List_add(list, whatever);
}