C语言中的结构指针
结构问题 我编写了一个实现堆栈的代码。如果我将sqStack*sq传递给这个函数init_stack,代码将以一个错误结束。如下面代码的注释所示。 但后来我发现,如果我将sqStack&sq传递给init_stack函数,代码就会工作。 谁能给我解释一下吗?谢谢C语言中的结构指针,c,pointers,struct,C,Pointers,Struct,结构问题 我编写了一个实现堆栈的代码。如果我将sqStack*sq传递给这个函数init_stack,代码将以一个错误结束。如下面代码的注释所示。 但后来我发现,如果我将sqStack&sq传递给init_stack函数,代码就会工作。 谁能给我解释一下吗?谢谢 #include <stdio.h> #include <stdlib.h> #define init_size 10 #define increment 1 typedef struct sqStack {
#include <stdio.h>
#include <stdlib.h>
#define init_size 10
#define increment 1
typedef struct sqStack
{
int* top;
int* base;
int stack_size;
}sqStack;
int init_stack(sqStack* sq)
{
if(sq->base==NULL)
{
sq->base = (int*)malloc(init_size*sizeof(int));
}
if(sq->base==NULL) exit(-1);
sq->stack_size=init_size;
sq->top=NULL;
sq->top=sq->base;
return 1;
}
int push(sqStack* sq, int e)
{
if(sq==NULL) exit(-1);
if(sq->top-sq->base==sq->stack_size)
{
int* q = (int*)realloc(sq->base,
(init_size+increment)*sizeof(int));
if(q==NULL) exit(-1);
sq->base=q;
sq->stack_size += increment;
sq->top=sq->base+sq->stack_size;
}
*sq->top++=e;//Thread 1: EXC_BAD_ACCESS If I pass sqStack* sq to this function, error occurs. But if I pass sqStack &sq, the code works.
return 1;
}
int pop(sqStack* sq,int*e)
{
if(sq==NULL) exit(-1);
if(sq->base==sq->top) exit(-1);
sq->top-=1;
*e=*sq->top;
return 1;
}
int empty(sqStack* sq)
{
if(sq->base==sq->top) return 1;
else return 0;
}
int main()
{
sqStack* sq;
init_stack(sq);
push(sq,1);
int e=
pop(sq,e);
printf("%d\n",*e);
/* sqStack sq;
init_stack(&sq);
push(&sq,1);
int e;
pop(&sq,&e);
printf("%d\n",e);*/
return 0;
}
在任何一种情况下,输出都是1。这里您取消了对未初始化悬挂指针的引用:
sqStack* sq;
init_stack(sq);
在init_堆栈中:
if(sq->base==NULL)
...
这会立即导致未定义的行为
最好这样做:
sqStack sq;
init_stack(&sq);
现在,在进程堆栈上为sqStack正确分配空间,并将指向该空间的指针传递给init_堆栈。每次您想要传递指向该结构的指针时(例如,在pop和push中),您必须立即使用&sq
或者,您可以像下面这样为sqStack动态分配内存:
sqStack *sq = malloc(sizeof(sqStack));
init_stack(sq);
这一次也会在堆上保留内存
第三种变体是将结构的分配留给init_stack函数。在这种情况下,您必须向init_stack传递一个双指针,以便可以将地址写入其中,并自行添加错误检查:
int init_stack(sqStack** _sq) {
sqStack* sq;
sq = *_sq = malloc(sizeof(sqStack));
sq->base = malloc(init_size*sizeof(int));
...
主要是:
sqStack *sq;
init_stack(&sq);
...
在这里,您将取消引用未初始化的悬挂指针:
sqStack* sq;
init_stack(sq);
在init_堆栈中:
if(sq->base==NULL)
...
这会立即导致未定义的行为
最好这样做:
sqStack sq;
init_stack(&sq);
现在,在进程堆栈上为sqStack正确分配空间,并将指向该空间的指针传递给init_堆栈。每次您想要传递指向该结构的指针时(例如,在pop和push中),您必须立即使用&sq
或者,您可以像下面这样为sqStack动态分配内存:
sqStack *sq = malloc(sizeof(sqStack));
init_stack(sq);
这一次也会在堆上保留内存
第三种变体是将结构的分配留给init_stack函数。在这种情况下,您必须向init_stack传递一个双指针,以便可以将地址写入其中,并自行添加错误检查:
int init_stack(sqStack** _sq) {
sqStack* sq;
sq = *_sq = malloc(sizeof(sqStack));
sq->base = malloc(init_size*sizeof(int));
...
主要是:
sqStack *sq;
init_stack(&sq);
...
问题解决方案
问题在于你保留了记忆
将sq用作指针。为什么会有问题
嗯,我们只有空间来存放sqStack的地址。
如果我们将sq传递给init_堆栈,我们将取消引用
sq.这不会导致任何结果,因为我们将其初始化为
指针,因此,如果我们试图给它的字段赋值,
我们没有空间放它
如何解决这个问题?只需将sq初始化为
sqStack而不是指向它的指针:
sqStack sq;
init_stack(&sq); /* pass by reference here */
/* code continued */
建议
另外,我认为更好的结构应该是
typedef struct sqStack {
int *elements;
int top;
}
通过这种方式,您可以使用顶部作为跟踪的手段
只需将元素存储在
特别分配的数组。这样看起来
void push(sqStack *sq, int element) {
sq->top++;
if (sq->top - 1 == 0) {
/* we need to allocate space */
sq->elements = malloc(sizeof(int));
} else {
/* we need to reallocate space */
sq->elements = realloc(sq->elements, sq->top * sizeof(int));
}
sq->elements[sq->top - 1] = element;
}
…并以类似方式修改其他功能。但是
这只是一个建议。问题解决方案
问题在于你保留了记忆
将sq用作指针。为什么会有问题
嗯,我们只有空间来存放sqStack的地址。
如果我们将sq传递给init_堆栈,我们将取消引用
sq.这不会导致任何结果,因为我们将其初始化为
指针,因此,如果我们试图给它的字段赋值,
我们没有空间放它
如何解决这个问题?只需将sq初始化为
sqStack而不是指向它的指针:
sqStack sq;
init_stack(&sq); /* pass by reference here */
/* code continued */
建议
另外,我认为更好的结构应该是
typedef struct sqStack {
int *elements;
int top;
}
通过这种方式,您可以使用顶部作为跟踪的手段
只需将元素存储在
特别分配的数组。这样看起来
void push(sqStack *sq, int element) {
sq->top++;
if (sq->top - 1 == 0) {
/* we need to allocate space */
sq->elements = malloc(sizeof(int));
} else {
/* we need to reallocate space */
sq->elements = realloc(sq->elements, sq->top * sizeof(int));
}
sq->elements[sq->top - 1] = element;
}
…并以类似方式修改其他功能。但是
这只是一个建议。在主函数中有指针sq,但它指向哪里?我建议您将其更改为非指针,并使用运算符的地址&当需要指向它的指针时。&基本上是指指向的指针。这是一个经典问题。返回分配的节点或使用指向指针的指针。在C语言中,应该将指向X的指针传递给希望修改X的函数。在这种情况下,由于您希望修改指针,因此应该将指针传递给指针。在main函数中,您有指针sq,但它指向哪里?我建议您将其更改为非指针,并使用运算符的地址&当需要指向它的指针时。&基本上是指指向的指针。这是一个经典问题。返回分配的节点或使用指向指针的指针。在C语言中,应该将指向X的指针传递给希望修改X的函数。在这种情况下,因为您希望修改指针,所以应该将指针传递给指针。谢谢!并且是sq->top=NULL;在init_堆栈中,代码中需要用到???@Liu No,因为您在下一行sq->top=sq->base中覆盖了它;你可以省略这个,谢谢!我现在知道我的代码有问题,但是为什么我用同样的方法创建一个序列,结果很好,为什么?如果我动态地为sqStack sqStack*sq=mallocsizeofsqStack分配内存;init_stacksq;sq没有初始化,在将其传递给push之后,代码被压碎了,我应该如何修复它??@Li
你必须显示完整的代码,即编辑你的问题并将其添加到那里谢谢!并且是sq->top=NULL;在init_堆栈中,代码中需要用到???@Liu No,因为您在下一行sq->top=sq->base中覆盖了它;你可以省略这个,谢谢!我现在知道我的代码有问题,但是为什么我用同样的方法创建一个序列,结果很好,为什么?如果我动态地为sqStack sqStack*sq=mallocsizeofsqStack分配内存;init_stacksq;sq未初始化,在将其传递到push后,代码被压碎,我应该如何修复它???@Liu您必须显示完整的代码,即编辑您的问题并将其添加到那里谢谢!并且是sq->top=NULL;在代码中需要的init_堆栈中???@Liu我添加了一个间接解决您问题的建议。一个建议??谢谢!我现在知道我的代码有问题,但是为什么我用类似的方法创建序列,结果很好,为什么?谢谢!并且是sq->top=NULL;在代码中需要的init_堆栈中???@Liu我添加了一个间接解决您问题的建议。一个建议??谢谢!我现在知道我的代码有问题,但为什么我用类似的方法创建序列,结果很好,为什么??