c - C中的结构指针
问题描述
结构问题。
我写了一个实现堆栈的代码。如果我将 sqStack* sq 传递给这个函数 init_stack(),代码最终会出错。如以下代码的注释所示。
但后来我发现如果我将 sqStack &sq 传递给 init_stack() 函数,代码就可以工作。
谁能给我解释一下?谢谢!
#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_stack() 中):
if(sq->base==NULL)
...
这会立即导致未定义的行为。
最好这样做:
sqStack sq;
init_stack(&sq);
现在您在进程堆栈上为 sqStack 正确分配空间,并将指向该空间的指针传递给init_stack()
. 每次你想传递一个指向那个结构的指针(例如 inpop
和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);
...
推荐阅读
- python - Pytorch - torchvision.dataset.ImageFolder 的子类 - 导入错误
- python - 如何将每个熊猫分组写入单独的 .csv 文件?
- java - 使用 CruiseControl.net 运行 jUnit 并在 CruiseControl.NET 的仪表板中显示结果
- c# - 实例和进程之间的区别
- c# - 如何在 Azure Functions 中实现指数退避?
- vba - VBA 在频繁打开/关闭时跳过写入文本文件
- reactjs - StackNavigation 的 ReactNavigation.setParams?
- javascript - Wix 网站需要 Javascript 以通过 API 服务发送提交表单的电子邮件
- excel - 在 VBA Excel 中按 Enter 后,将注意力集中在文本框上
- loops - VueJS:v-for 中的表单 - 如何获取正确的数据?