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-

我还在学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->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*) &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");
    }
}


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: