#include <stdio.h>
#include <stdlib.h>
typedef struct {
unsigned length;
} List;
void init(List *l) {
l = (List *) malloc(sizeof(List));
l->length = 3;
}
int main(void) {
List *list = NULL;
init(list);
if(list != NULL) {
printf("length final %d \n", list->length);
return 0;
}
return 1;
}
这是给我提问的代码的简化版本。我正在尝试从*list
作为参数传递的方法构造指针*list
。
我知道我可以通过将其更改为void init(List *l)
来使void init(List **l)
工作,但这是针对课程教程的。我无法更改方法参数。我花了四个小时研究这个。
我想确保在面对我的教授之前没有办法让void init(List *l)
工作。
提前致谢
答案 0 :(得分:4)
您将指针的副本传递给init
,它正在分配内存,将其存储在本地副本中,并在init
返回时立即泄漏。您不能以这种方式将数据传回给调用函数。您需要返回已分配的数据,或者将指针传递给要修改的指针,这两者都涉及修改函数签名。
void init(List **l) {
*l = (List *) malloc(sizeof(List));
(*l)->length = 3;
}
init(&list);
作业是否指定您必须从List
内分配init
?如果没有,您可以始终将指针传递给已分配的List
对象,并执行任何初始化length = 3
作为占位符:
void init(List *l) {
l->length = 3;
}
List list;
init(&list);
printf("length final %d \n", list.length);
答案 1 :(得分:3)
问题是指针是按值传递的,因此您的更改将被丢弃。你真的需要一个指向指针才能正确执行此操作。和你一样:
void init(List** l) {
*l = (List*) malloc(sizeof(List));
// ...
}
当您致电时,您会使用init(&list)
代替init(list)
。当然,在这种情况下,只需继续并返回结果而不是使用指向指针的指针是有意义的:
List* init() {
List* result = (List *) malloc(sizeof(List));
result->length = 3;
return result;
}
然后,通过上述内容,您只需使用list = init();
。
请注意,在C ++中,您可以使用引用而不是指针,但混合引用和指针是非常混乱的。在这里,使用返回类型确实是最好的事情。
如果你必须使用现有的签名,你可以偷偷摸摸地初始化列表,然后在init()
函数中,你可以使传入列表的下一个指针指向你真正想要创建的列表。然后,在调用init()
之后,您可以获取下一个指针并处理您创建的原始列表对象。或者你总是可以通过一些虚拟元素获得第一个元素。
答案 2 :(得分:1)
这个赋值可能是在类中传递值并通过引用传递的好方法。如果要维护构造函数的签名,则需要修改main函数。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
unsigned length;
} List;
void init(List *l) {
l->length = 3;
}
int main(void) {
List list;// x = NULL;
memset(&list,0,sizeof(List));
init(&list);
printf("length final %d \n", list.length);
return 1;
}
现在这里的列表是List类型而不是List的地址。 init()方法传递list的地址,在init中你可以改变结构内容的值。
./ a.out
长度决赛3
答案 3 :(得分:0)
init需要传递一个指向现有List的指针。我怀疑这里的真正问题在于您的数据结构。你有一个名为List的东西,它包含一个长度,但是没有列表可以在任何地方看到。 List应该包含指向给定长度数组的指针,init应该malloc那个数组并设置指针。当你要求教授纠正他的要求时,你可能会发现这一点,而这些要求并没有被打破 - 如果是这样的话,他可能会从过去的学生那里听到它并立即纠正它们。