我还在学习C,我必须在某些时候误解指针。
我认为以下行会将l->first
存储的内存地址复制到temp
。它们都是struct list_el*
指针,所以我看不出问题。
struct list_elt * temp;
temp = l->first;
运行我的示例代码给了我一个无限循环:
user@machine:~$ gcc question.c
user@machine:~$ ./a.out | head
append(): l->first->val: 30, l->first->next == NULL: 1
main() : l->first->val: 30, l->first->next == NULL: 1
print() : l->first->val: 30, l->first->next == NULL: 1
print() : temp->val: 30, temp->next == NULL: 0
print() : temp->val: 30, temp->next == NULL: 0
print() : temp->val: 30, temp->next == NULL: 0
print() : temp->val: 30, temp->next == NULL: 0
print() : temp->val: 30, temp->next == NULL: 0
print() : temp->val: 30, temp->next == NULL: 0
print() : temp->val: 30, temp->next == NULL: 0
这是question.c
。对不起,我无法进一步缩小范围,每次我做这个问题似乎神奇地消失了。
#include <stdio.h>
#include <stdlib.h>
struct list_elt {
int val;
struct list_elt * next;
};
struct linked_list {
struct list_elt* first;
};
void print(const struct linked_list * l);
struct linked_list* new_list(void);
void append(struct linked_list* l, int value);
main()
{
struct linked_list * l;
l = new_list();
append(l, 30);
printf("main() : l->first->val: %d, l->first->next == NULL: %d\n", l->first->val, l->first->next == NULL);
print(l);
}
struct linked_list* new_list()
{
struct linked_list* l;
l = (struct linked_list*) malloc(sizeof(struct linked_list));
l->first = NULL;
return l;
}
void append(struct linked_list* l, int value)
{
struct list_elt el = {0, NULL};
el.val = value;
el.next = NULL;
if (l->first == NULL) {
l->first = (struct list_elt*) ⪙
printf("append(): l->first->val: %d, l->first->next == NULL: %d\n", l->first->val, l->first->next == NULL);
} else {
printf("append(): Unimplemented\n");
}
}
void print(const struct linked_list * l)
{
printf("print() : l->first->val: %d, l->first->next == NULL: %d\n", l->first->val, l->first->next == NULL);
struct list_elt * temp;
temp = l->first;
while (temp != NULL) {
printf("print() : temp->val: %d, temp->next == NULL: %d\n", temp->val, temp->next == NULL);
temp = temp->next;
}
printf("\n");
}
感谢。
答案 0 :(得分:5)
您正在append
函数的堆栈上分配list_elt。函数返回后该指针无效,不应再引用。
您应该使用malloc
来分配元素。
答案 1 :(得分:3)
在append()
中,您将l->first
设置为本地堆栈变量el
的地址。但是el
一旦append()
返回就会超出范围,因此之后任何取消引用l->first
的尝试都是未定义的行为。
答案 2 :(得分:3)
(以下是一个非常简单的解释,非常简单,以至于它可以说是非常简洁。我只是为了简单,但你可以通过谷歌搜索堆栈和C中的堆来了解更多。)
基本上有两种方法可以创建并将它们存储在内存中:使用堆栈,或者向操作系统请求内存。
堆栈是临时内存,用于跟踪当前执行上下文。每次调用函数时,堆栈的一个扇区都用于存储所有局部变量。这就是您在append()
中所做的事情:使用位于堆栈中的临时内存来存储新的列表节点。
堆栈中的任何内容(任何局部变量)在从函数返回时被视为时间和空间丢失,因为当前执行上下文不再相关,并且该存储器被重用于另一个上下文(例如,下一个函数调用)。这是不可避免的,这是这个内存管理方式的结果,它发生在C的直接范围之外(或者更确切地说,你不应该把它弄乱)。
如果您希望在本地范围之外存储与程序相关的内容,而不仅仅是当前执行上下文,您必须向操作系统请求额外的内存 - 此临时< em> stack 不会这样做。有很多功能 - 请查看最简单的malloc()
。
希望它有所帮助。干杯!
答案 3 :(得分:1)
您的append
功能错误。它在堆栈上分配el
,并使用列表中的指针。这样做的问题是,在append
之后调用另一个函数时,内存将被垃圾覆盖,在本例中为print
。相反,使用malloc进行分配,例如:
int append(struct linked_list* l, int value)
{
struct list_elt *el = malloc(sizeof(struct list_elt));
if (el)
{
el->val = value;
el->next = NULL;
if (l->first == NULL) {
l->first = el;
printf("append(): l->first->val: %d, l->first->next == NULL: %d\n",
l->first->val, l->first->next == NULL);
} else {
printf("append(): Unimplemented\n");
}
return 0;
}
else
{
return 1;
}
}
答案 4 :(得分:0)
在附加中,您的元素在堆栈上创建并稍后引用:这是错误的。当您的函数退出时,el
变量不再存在。你需要malloc你的list_elt。