C 堆栈中的推送操作出现逻辑错误

C 堆栈中的推送操作出现逻辑错误,c,arrays,data-structures,struct,stack,C,Arrays,Data Structures,Struct,Stack,我正在以数组的形式对堆栈执行插入操作,但我的程序在输入第一个值时崩溃 typedef struct Stack { int top; int elements[20]; } stack; stack *s; void push(int x) { s->top++; if(s->top<=19){ s->elements[s->top]=x;} else puts("Overflow"); } typedef结构堆栈 { int t

我正在以数组的形式对堆栈执行插入操作,但我的程序在输入第一个值时崩溃

typedef struct Stack
{
  int top;
  int elements[20];
}
stack;
stack *s;

void push(int x)
{
  s->top++;
  if(s->top<=19){
  s->elements[s->top]=x;}
  else
    puts("Overflow");
}
typedef结构堆栈
{
int top;
int元素[20];
}
堆栈
堆栈*s;
无效推送(整数x)
{
s->top++;
如果(s->topelements[s->top]=x;}
其他的
看跌期权(“溢出”);
}

根据您当前的代码,看起来您正在使用未初始化的
s
。使用单元化内存调用,这反过来可能会导致分段错误

为了防止单元化的
s
,您可能需要修改代码,如

void push(int x)
{
  if (s)         //check if `s` has been initialized.
  {
      s->top++;
      if(s->top<=19)
      {
          s->elements[s->top]=x;
      }
      else
          puts("Overflow");
  }
  else
      //abort, return error or something similar
}
无效推送(int x)
{
if(s)//检查's'是否已初始化。
{
s->top++;
如果(s->topelements[s->top]=x;
}
其他的
看跌期权(“溢出”);
}
其他的
//中止、返回错误或类似情况
}

注:

除了手头的问题外,还有一个隐藏的问题,在您解决此问题后,它将立即出现

push()
函数中,您无条件地增加
top
值。这意味着,即使堆栈已满,您的
top
值也将增加,稍后将导致错误计算


您还必须在值范围检查下移动堆栈
顶部
增量部分。

看起来您只是定义了一个struct stack类型的指针,但没有分配堆栈本身

stack *s;
因此s等于NULL。至少您应该分配堆栈本身。例如

stack *s;

//...
s = malloc( sizeof( struct Stack ) );
stack s;
但在任何情况下都不需要定义指针。您可以定义堆栈本身。例如

stack *s;

//...
s = malloc( sizeof( struct Stack ) );
stack s;
Aldo您需要设置数据成员top的初始值。我认为您可以使用-1初始化它

此外,函数insert本身无效

void push(int x)
{
  s->top++;
  if(s->top<=19){
  s->elements[s->top]=x;}
  else
    puts("Overflow");
}
无效推送(int x)
{
s->top++;
如果(s->topelements[s->top]=x;}
其他的
看跌期权(“溢出”);
}
每次调用该函数时,它都会增加数据成员top,即使它已指向数组之外

void push(int x)
{
   if ( s->top + 1 < 20)
   {
      s->elements[++s->top] = x;
   }
   else
   [
       puts("Overflow");
   }
}
无效推送(int x)
{
如果(s->top+1<20)
{
s->elements[++s->top]=x;
}
其他的
[
看跌期权(“溢出”);
}
}

检查
如果(s)
有点棘手;它可以被用户释放
s
-并且没有设置为NULL。因此检查将是正常的-实际上是UB@Giorgi是的,但是大多数时候,添加一个简单的空检查可以为您节省很多麻烦。:-)顺便说一句,您有什么改进建议吗?可能会告诉用户在释放后将指针设置为NULL,否则if语句将触发UB:。如果您能够确保指针不为NULL这一事实意味着指针有效,那么这些if语句是有意义的-在Linux上,这可能会更加棘手,例如malloc可能失败并返回notnull@Giorgi我完全同意。上面的信息非常有用,但我认为,在当前场景中有点脱离上下文。我们不知道
free()
ing部分实现,是吗?不过,感谢您提供的有用信息。希望它能帮助某人。:-)是的,你是对的。在释放
s
时调用
push
也没有意义;但该检查也不会保存你。除非你在释放后将其设置为NULL。但是,malloc/Linux问题将是另一个问题