C 分段故障(堆芯转储)堆栈

C 分段故障(堆芯转储)堆栈,c,stack,C,Stack,我试图实现一个简单的堆栈,但我有一个分段问题: struct node { int key; struct node *next; }; static struct node *head, *z, *t; int main(int argc, char** argv) { push(5); push(9); push(8); push(pop()+pop()); push(4); push(6); push(pop()*p

我试图实现一个简单的堆栈,但我有一个分段问题:

struct node {
    int key;
    struct node *next;
};
static struct node *head, *z, *t;

int main(int argc, char** argv) {
    push(5);
    push(9);
    push(8);
    push(pop()+pop());
    push(4);
    push(6);
    push(pop()*pop());
    push(pop()*pop());
    push(7);
    push(pop()+pop());
    push(pop()*pop());
    printf("%d\n", pop());
    return (EXIT_SUCCESS);
}

stackinit() {
    head = (struct node*) malloc(sizeof *head);
    z = (struct node*) malloc(sizeof *z);
    head->next = z;
    head->key = 0;
    z->key = 0;
    z->next = z;
}

stackempty() {
    return head->next == z;
}

int pop() {
    int x;
    t = head->next;
    head->next = t->next;
    x = t->key;
    free(t);
    return x;
}

push(int v) {
    t = (struct node*) malloc(sizeof *t);
    t->key = v;
    t->next = head->next;
    head->next = t;

}
给出的错误是:分段错误(堆芯转储)

我知道我在寻找一个不存在的id,但我不知道为什么

有人知道为什么? 谢谢 在推送中致以最诚挚的问候:

t->next = head->next
head->next = t;
应该是:

t->next = head;
head = t;
您要做的是首先假装
t
是新的头部,因此您将下一个指针设置为指向当前头部。如果我们想象
head
A
,堆栈中的元素是
B
,那么我们首先将
t
搁浅在一侧:

t = new_node;
-- t  A(head)->B->...->NULL
第一行钩住
t
头部,如下所示:

t->next = head;
-- t->A(head)->B->...
然后第二个使
t
成为新的头部

head = t;
-- t(head)->A->B->...->NULL
现在,您的pop也有一些问题:

t = head->next;
head->next = t->next;
这应该是:

t = head;
head = head->next;
我们正在做的是将当前头复制到
t
,这样我们就不会丢失它,然后下一行是弹出堆栈的实际行(将头更改为指向堆栈下面的元素)

我真的建议您在编写代码之前在纸上绘制这个。它会帮助你更快地学习

最后但并非最不重要的一点是,您需要调用这个
stackinit
函数来正确初始化所有内容,但您没有调用它。在里面,我不确定z应该做什么,但这肯定是错误的:

z->next = z;
这将使
z
循环,就像这样:
z->z->z->z->……

在推送中:

t->next = head->next
head->next = t;
应该是:

t->next = head;
head = t;
您要做的是首先假装
t
是新的头部,因此您将下一个指针设置为指向当前头部。如果我们想象
head
A
,堆栈中的元素是
B
,那么我们首先将
t
搁浅在一侧:

t = new_node;
-- t  A(head)->B->...->NULL
第一行钩住
t
头部,如下所示:

t->next = head;
-- t->A(head)->B->...
然后第二个使
t
成为新的头部

head = t;
-- t(head)->A->B->...->NULL
现在,您的pop也有一些问题:

t = head->next;
head->next = t->next;
这应该是:

t = head;
head = head->next;
我们正在做的是将当前头复制到
t
,这样我们就不会丢失它,然后下一行是弹出堆栈的实际行(将头更改为指向堆栈下面的元素)

我真的建议您在编写代码之前在纸上绘制这个。它会帮助你更快地学习

最后但并非最不重要的一点是,您需要调用这个
stackinit
函数来正确初始化所有内容,但您没有调用它。在里面,我不确定z应该做什么,但这肯定是错误的:

z->next = z;
这将使
z
循环,就像这样:
z->z->z->z->……

在推送中:

t->next = head->next
head->next = t;
应该是:

t->next = head;
head = t;
您要做的是首先假装
t
是新的头部,因此您将下一个指针设置为指向当前头部。如果我们想象
head
A
,堆栈中的元素是
B
,那么我们首先将
t
搁浅在一侧:

t = new_node;
-- t  A(head)->B->...->NULL
第一行钩住
t
头部,如下所示:

t->next = head;
-- t->A(head)->B->...
然后第二个使
t
成为新的头部

head = t;
-- t(head)->A->B->...->NULL
现在,您的pop也有一些问题:

t = head->next;
head->next = t->next;
这应该是:

t = head;
head = head->next;
我们正在做的是将当前头复制到
t
,这样我们就不会丢失它,然后下一行是弹出堆栈的实际行(将头更改为指向堆栈下面的元素)

我真的建议您在编写代码之前在纸上绘制这个。它会帮助你更快地学习

最后但并非最不重要的一点是,您需要调用这个
stackinit
函数来正确初始化所有内容,但您没有调用它。在里面,我不确定z应该做什么,但这肯定是错误的:

z->next = z;
这将使
z
循环,就像这样:
z->z->z->z->……

在推送中:

t->next = head->next
head->next = t;
应该是:

t->next = head;
head = t;
您要做的是首先假装
t
是新的头部,因此您将下一个指针设置为指向当前头部。如果我们想象
head
A
,堆栈中的元素是
B
,那么我们首先将
t
搁浅在一侧:

t = new_node;
-- t  A(head)->B->...->NULL
第一行钩住
t
头部,如下所示:

t->next = head;
-- t->A(head)->B->...
然后第二个使
t
成为新的头部

head = t;
-- t(head)->A->B->...->NULL
现在,您的pop也有一些问题:

t = head->next;
head->next = t->next;
这应该是:

t = head;
head = head->next;
我们正在做的是将当前头复制到
t
,这样我们就不会丢失它,然后下一行是弹出堆栈的实际行(将头更改为指向堆栈下面的元素)

我真的建议您在编写代码之前在纸上绘制这个。它会帮助你更快地学习

最后但并非最不重要的一点是,您需要调用这个
stackinit
函数来正确初始化所有内容,但您没有调用它。在里面,我不确定z应该做什么,但这肯定是错误的:

z->next = z;

这使得
z
循环,就像这样:
z->z->z->z->……

z->next=z这有什么意义?分配2个头部节点而不是1个有什么意义?此外,如果使用现代编译器编译,则代码不是有效的C。所有函数都必须有一个返回类型,隐式int在16年前就从语言中删除了这有什么意义?分配2个头部节点而不是1个有什么意义?此外,如果使用现代编译器编译,则代码不是有效的C。所有函数都必须有一个返回类型,隐式int在16年前就从语言中删除了这有什么意义?分配2个头部节点而不是1个有什么意义?此外,如果使用现代编译器编译,则代码不是有效的C。所有函数都必须有一个返回类型,隐式int在16年前就从语言中删除了