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年前就从语言中删除了