C 将结构指针元素复制到指针似乎会损坏它
我还在学C,我一定在某个时候误解了指针 我的印象是,下面几行会将C 将结构指针元素复制到指针似乎会损坏它,c,C,我还在学C,我一定在某个时候误解了指针 我的印象是,下面几行会将l->first存储的内存地址复制到temp。它们都是结构列表*指针,所以我看不出问题所在 struct list_elt * temp; temp = l->first; 运行示例代码会给我一个无限循环: user@machine:~$ gcc question.c user@machine:~$ ./a.out | head append(): l->first->val: 30, l->first-
l->first
存储的内存地址复制到temp
。它们都是结构列表*
指针,所以我看不出问题所在
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
下面是问题.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");
}
#包括
#包括
结构列表{
int-val;
结构列表_elt*下一步;
};
结构链表{
首先是结构列表;
};
无效打印(常量结构链接列表*l);
结构链接列表*新列表(无效);
void append(结构链接列表*l,int值);
main()
{
结构链接列表*l;
l=新列表();
追加(l,30);
printf(“main():l->first->val:%d,l->first->next==NULL:%d\n”,l->first->val,l->first->next==NULL);
印刷品(l);
}
结构链接列表*新列表()
{
结构链接列表*l;
l=(结构链接列表*)malloc(sizeof(结构链接列表));
l->first=NULL;
返回l;
}
void append(结构链接列表*l,int值)
{
结构列表_eltel={0,NULL};
el.val=值;
el.next=NULL;
如果(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);
}否则{
printf(“append():未实现\n”);
}
}
无效打印(常量结构链接列表*l)
{
printf(“print():l->first->val:%d,l->first->next==NULL:%d\n”,l->first->val,l->first->next==NULL);
结构列表_elt*temp;
温度=l->第一;
while(temp!=NULL){
printf(“print():temp->val:%d,temp->next==NULL:%d\n”,temp->val,temp->next==NULL);
温度=温度->下一步;
}
printf(“\n”);
}
谢谢。您正在
append
函数的堆栈上分配列表。函数返回后,此指针无效,不应再被引用
您应该使用
malloc
来分配元素。在append()
中,您将l->first
设置为本地堆栈变量el
的地址。但是el
一旦返回append()
就会超出范围,因此任何先取消引用l>后取消引用的尝试都是未定义的行为。在append中,您的元素在堆栈上创建,稍后再引用:这是错误的。当函数退出时,el
变量不再存在。您需要对列表进行malloc\u elt。您的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;
}
}
(下面是一个非常简单的解释,简单到可以说是不精确的。我是为了简单起见,但是你可以通过谷歌搜索C中的堆栈和堆来了解更多)
创建内容并将其存储在内存中基本上有两种方法:使用堆栈,或向操作系统请求内存
堆栈是临时内存,用于跟踪当前执行上下文。每次调用函数时,堆栈的一个扇区用于存储所有局部变量。这就是您在append()
:中使用堆栈中的临时内存来存储新列表节点的操作
当您从函数返回时,堆栈中的任何内容(任何局部变量)都会被视为在时间和空间上丢失,因为当前执行上下文不再相关,并且该内存会被重新用于另一个上下文(例如,下一个函数调用)。这是不可避免的,这是如何管理内存的结果,在C语言中,它发生在您直接接触不到的地方(或者更确切地说,您不应该弄乱它)
当您希望存储此本地范围之外的内容时,通常与您的程序相关,而不仅仅是与当前执行上下文相关,您必须向操作系统请求额外内存——此临时堆栈不起作用。有很多函数可以实现这一点——请查看最简单的函数malloc()
希望有帮助。干杯 似乎是作业
:如果是这样,请正确标记,否则,请使用库;-)啊!不要为对象命名l
。如果必须使用单个字母,请使用任何其他字母(除了I
或O
);但无论如何,最好使用多于一个字母。这个问题确实是在家庭作业中出现的,如果你愿意,请继续添加正确的标签。实际上,我用指针替换了el
,并使用了malloc
,从而完成了这篇作业,但我想知道为什么这个版本不起作用。我同意单字母变量名很可怕,但信不信由你,这实际上是我不止一位讲师的常见做法。为了stackoverflow的利益,我应该重新命名它,对不起!注意,在C中,不强制转换malloc()
的返回值被认为是一种良好的做法。在尝试使用指针之前,检查malloc是否返回0/NULL被认为是一种良好的做法。这很有意义。是否仍可以保持el
原来的list\u elt
结构而不是指向某个结构的指针?@Flimm,el
必须是指针,因为结构的内存需要由malloc
分配。如果将其设置为之前的值,则内存将在堆栈上本地分配,并将被另一个函数调用覆盖。@Flimm: