在C中使用结构和指针时出现分段错误

在C中使用结构和指针时出现分段错误,c,pointers,struct,stack,C,Pointers,Struct,Stack,我想用C语言实现一些基本的数据结构,以便学习如何使用指针,但我在第一个方面遇到了困难;我有两个结构: typedef struct node{ int value; struct node* next; }Node; typedef struct stack{ int qtd; Node* top; }Stack; 这些功能包括: Stack newStack(void){ Stack tmp; tmp.qtd = 0; tmp.top = NULL; re

我想用C语言实现一些基本的数据结构,以便学习如何使用指针,但我在第一个方面遇到了困难;我有两个结构:

typedef struct node{
  int value;
  struct node* next;
}Node;


typedef struct stack{
  int qtd;
  Node* top;
}Stack;
这些功能包括:

Stack newStack(void){
  Stack tmp;
  tmp.qtd = 0;
  tmp.top = NULL;
  return tmp;
}

void push(Stack s, int value){
  if( s.qtd == 0 ){
    s.top->value = value; 
    s.qtd++;
  }
  else{
    Node* tmp = (Node*) malloc(sizeof(Node*));
    tmp->value = value;
    tmp->next = s.top;
    s.top = tmp; 
    s.qtd++;
  }
}
main()
函数中,I“初始化”堆栈(
stack s=newStack();

并使用(s,6)作为参数调用push函数。我在
s.top->value=value得到一个seg故障。怎么了?

您刚刚构建了堆栈
s
,因此
s.top
为空。然后你要这样做:

s.top->value = value;

取消引用空指针是未定义的行为。幸运的是,您得到的只是一个segfault。

您刚刚构建了堆栈
s
,因此
s.top
为空。然后你要这样做:

s.top->value = value;

取消引用空指针是未定义的行为。幸运的是,您得到的只是一个segfault。

您看到的是segfault,因为
top
被初始化为
NULL
,然后被取消引用。因为您正在实现一个堆栈,所以每个元素都被推到了顶部,所以不需要在
push
函数中检查它是否为空

另一个问题是,当分配
节点
时,它应该是
sizeof(Node)
,您只是分配了一个指针,而不是一个结构

此外,您应该将
Stack
作为指向堆栈的指针传递,而不是结构本身,因为
push
函数中的内容是结构的副本,因此更新其字段不会更新原始结构

尝试此推送功能:

void push(Stack *s, int value) {
    Node* tmp = (Node*) malloc(sizeof(Node));
    tmp->value = value;
    tmp->next = s->top;
    s->top = tmp;
    s->qtd++;
}
并通过以下方式分配堆栈:

Stack* newStack(void) {
    Stack *s = malloc(sizeof(Stack));
    s->qtd = 0;
    s->top = NULL;
    return s;
}

您之所以看到segfault,是因为
top
被初始化为
NULL
,然后被取消引用。因为您正在实现一个堆栈,所以每个元素都被推到了顶部,所以不需要在
push
函数中检查它是否为空

另一个问题是,当分配
节点
时,它应该是
sizeof(Node)
,您只是分配了一个指针,而不是一个结构

此外,您应该将
Stack
作为指向堆栈的指针传递,而不是结构本身,因为
push
函数中的内容是结构的副本,因此更新其字段不会更新原始结构

尝试此推送功能:

void push(Stack *s, int value) {
    Node* tmp = (Node*) malloc(sizeof(Node));
    tmp->value = value;
    tmp->next = s->top;
    s->top = tmp;
    s->qtd++;
}
并通过以下方式分配堆栈:

Stack* newStack(void) {
    Stack *s = malloc(sizeof(Stack));
    s->qtd = 0;
    s->top = NULL;
    return s;
}

除了前面提到的内容之外,还应该检查malloc的返回值,所以

Node* tmp = (Node*) malloc(sizeof(Node));
if (tmp == NULL)
{
    return; 
}

由于malloc不能保证成功,当您在内存不足的设备上工作时,这一点尤其令人担忧

除了前面提到的内容之外,还应该检查malloc的返回值,所以

Node* tmp = (Node*) malloc(sizeof(Node));
if (tmp == NULL)
{
    return; 
}

由于malloc不能保证成功,当您在内存不足的设备上工作时,这一点尤其令人担忧

在取消引用之前为
s.top
分配内存。您正在对堆栈上的
Stack
副本进行操作-即使分配内存,它仍然不太正确-您需要按引用传递。C使用按值传递。
push
函数修改其参数的副本;我猜在代码中的某个地方,你没有发布,而是推(a,b)
并期望
a
被更新在取消引用之前为
s.top
分配内存。您正在堆栈上对
堆栈的副本进行操作-即使您确实分配了内存,它仍然不太正确-您需要按引用传递。C使用按值传递。
push
函数修改其参数的副本;我猜在代码中的某个地方,你没有发布,而是推(a,b)并期望更新
a