结构体定义、结构体指针、内存分配、指针、结构体形参的深入理解

/*********结构体定义、结构体指针、内存分配、指针、结构体形参的深入理解**** 

作者: 攀枝花学院 袁伟明 

邮箱:
[email protected] 

说明:此程序为深入学习数据结构时候,对于数据结构最重要的基础(结构体、指针、内存分配) 方面的一些理解,我自己通过这段程序说明一些自己得到的结论;希望对看到这篇程序的c爱好者 有帮助,如果有理解错误的地方希望各位联系我,一起讨论学习.说实话,我学习c就半年吧,除了 上课自学的,发现最难的部分就是指针了.废话留在看了程序过后再说哈!为了方便我就在vc++ 上面编译运行的,我没有发现问题哈!程序的说明外加我自己的理解就在后面了: 

考虑: 
1.结构体指针变量与结构体变量怎样定义(typedef 有什么用处呢?与define有什么区别?) 
2.分配内存有malloc或者realloc等有什么区别 
3.结构体变量名与结构体变量指针名代表什么?和数组名一样代表首地址么 
4.结构体内的成员指针变量或者结构体指针变量是不是可以不初始化,如果要应该怎样初始化 
5.结构体指针变量与结构体变量怎样引用结构体成员变量的 
6.结构体与结构体指针用于怎样用于实参与形参的传递 
7.结构体定义过后就给结构体中的变量分配内存还是等待malloc分配呢 


请看程序吧: 
**************************************************************************/ 
#include<stdio.h> 
#include<stdlib.h> 

#define STACK_SIZE 1 
typedef int ElemType; 

//定义结构体// 
typedef struct sqstack 

ElemType *bottom; 
ElemType *top; 
int stacksize; 
}SqStack; 

//用于后面结构体形参的传递测试// 
void teststruct (SqStack *M) 

printf("M->stacksize=%d\n",M->stacksize); //观察形参传递是否正确 
M->stacksize++; 
printf("M->stacksize=%d\n",M->stacksize); //输出栈内的值 


void main() 

SqStack *S=NULL; //定义结构体指针,并初始化 
SqStack *G=NULL; //定义结构体指针 
SqStack P;//定义结构体 
SqStack Q;//定义结构体 
SqStack F;//定义结构体 

/************第一 结构体指针部分*************/ 

S=(SqStack *)malloc(STACK_SIZE*sizeof(SqStack)); //为结构分配一个空间大小的内存 
S->top=(ElemType *)malloc(STACK_SIZE*sizeof(ElemType)); //初始化结构体指针变量 
S->bottom=(ElemType *)malloc(STACK_SIZE*sizeof(ElemType)); //初始化初始化结构体指针变量 
/* 结构体变量赋值*/ 
*S->bottom=5; 
S->stacksize=6; 
*S->top=7; 

//值的输出 
printf("*S=%d\n",*S); //结构体第一个变量值的地址值,即S->bottom 
printf("*S->bottom=%d\n",*S->bottom); //变量*bottom的值 
printf("*S->top=%d\n",*S->top); //变量*top的值 
printf("S->stacksize=%d\n\n",S->stacksize); //变量stacksize的值 

//地址输出 
printf("&S=%d\n",&S); //即存放第一个变量值地址的地址的地址 
printf("S=%d\n",S); //存放第一个变量值地址的地址 
printf("S->bottom=%d\n",S->bottom);//*S->bottom的地址 
printf("&S->bottom=%d\n",&S->bottom);//S->bottom的地址 
printf("S->top=%d\n",S->top);//*S->top的地址 
printf("&S->top=%d\n",&S->top);//S->top的地址 
printf("&S->stacksize=%d\n",&S->stacksize);//S->stacksize的地址 

printf("\n\n\n"); 

/****************第二 结构体部分*****************/ 
/*结构体变量赋值*/ 
P.top=(ElemType *)malloc(STACK_SIZE*sizeof(ElemType)); //初始化 
P.bottom=(ElemType *)malloc(STACK_SIZE*sizeof(ElemType)); //初始化 

*(P.bottom)=5; 
*(P.top)=6; 
P.stacksize=7; 
//值的输出 
printf("P=%d\n",P);//P代表第一个变量地址存的值,由于第一变量是指针,所以存的是指针变量的地址p.bottom 
printf("*P.bottom=%d\n",*P.bottom);//指针变量的值 
printf("*P.top=%d\n",*P.top);//指针变量的值 
printf("P.stacksize=%d\n\n",P.stacksize);//结构体变量的值 
//地址输出 
printf("&P=%d\n",&P);//P的地址 
printf("P.bottom=%d\n",P.bottom);//*P.bottom的地址 
printf("&P.bottom=%d\n",&P.bottom);//P.bottom的地址 
printf("&P.top=%d\n",&P.top);//P.top的地址 
printf("P.top=%d\n",P.top);//*P.top的地址 
printf("&P.stacksize=%d\n",&P.stacksize);//P.stacksize的地址 

printf("\n\n\n"); 

/**************第三 结构体作为形参***************/ 

Q.stacksize=20; //结构体赋值 
teststruct(&Q); //函数调用处理 
printf("Q.stacksize=%d\n",Q.stacksize); //再次输出值观察是否变化 

printf("\n\n\n"); 

/**************第四 结构体指针作为形参************/ 

G=(SqStack *)malloc(STACK_SIZE*sizeof(SqStack)); //为结构分配一个空间大小的内存 
G->stacksize=30; //结构体赋值 
teststruct(G); //函数调用处理 
printf("G->stacksize=%d\n",G->stacksize); //再次输出值观察是否变化 
printf("\n\n\n"); 

/**************第五 结构体定义过后会产生的现象************/ 

printf("&F=%d\n",&F);//结构体名地址 
printf("&F.bottom=%d\n",&F.bottom);//F.bottom地址 
printf("&F.stacksize=%d\n",&F.stacksize);//F.stacksize地址 
printf("&F.top=%d\n",&F.top);//F.top地址 

/**************第六 重点理解指针*********** 
暂时没写 
*/ 
/**************第七 理解指针函数与函数指针*********** 
暂时没写 
*/ 

运行结果:

1.jpg

/****************************************第六 解释部分****************************** 
解释之前的废话:个人虽说学习c时间不长,但是要学得深入一点还真得把c与内存结合起来分析,有的只要加入了指针 就时常运行的时候发现程序突然中止不运行了,那么就多半是指针的问题了哦(这东西,用不好就是烦,用的好.真的是 一个不错的东西)! 
请看我的运行结果,因为运行的计算机和运行的时间不一样,反正就是不同时间不同计算机,结果出现不大一样是正 常的,但是本质都是一样的分析哦! 
1.结构体、结构体指针变量与结构体变量怎样定义(typedef 有什么用处呢?与define有什么区别?) 
都看到我定义了一个含有指针变量的结构体,那一处用了typedef的,而且在前面也是用了的,以结构体为例,我用了 typedef后那么 struct sqstack 就可以用SqStack这个代表了,所以我后面定义结构体变量的时候都用的这个了;typ edef与define的区别就是前者是定义了一个别名一样,后者是替换.定义结构体变量与结构体变量就和平常的变量一定 义就ok,上面我就定义了好几个,可以参考哦! 
2.分配内存有malloc或者realloc等有什么区别,怎样转换返回地址的类型? 
这个吧!百度上面有的,我自己弄了过后,说一下自己的感触,我们一般把malloc用于重新分配新内存,而realloc用 于增加内存分配,一般是连续的,如果内存不够就会重新分配,然后把原来内存中的东西复制过去,如果还是不理解就 看其代码!说道强制转换这个问题,其实在c++里面好像没有咋用,但是用了是绝对保险的;怎样强制转换看例子就好了, 至于什么类型呢?就看你赋值给谁咯。 
3.结构体变量名与结构体变量指针名代表什么?和数组名一样代表首地址么 
先看结构体指针名S与*S、&S分别指什么呢,我们可以发现S是分配内存的首地址,&S是存储这个首地址的地方,而&S-> bottom恰好是S的地址.这是表明结构体指针名S就表示首地址么,其实我们分析一下,我们定义结构体指针的时候会分 配一个地址&S,我们默认的是S=NULL就是空指针,但是分配内存过后就赋值给了S,指向一段内存,分配大小就是结构体 的大小,那么结构体的成员存储会不会在这个里面呢?显然答案是肯定的。因此我们会发现后面的&S->top的地址也是在 这个空间段上面,即malloc分配的内存就可以得到了。那么我们现在来分析P、&p、&p.bottom、p.bottom;这里需要说明 为啥我还要给结构体成员里面的指针初始化分配内存,这个是什么意思呢?在这里我只说一句:指针要么是NULL要么一定 要给一个内存的额地址;不然乱指可是会出大问题的在这里我们会发现&p与&p.bottom地址是一样的,而p与p.bottom的值 是一样的,这是为什么呢?这里我要解释一下,其实在定义结构体P的时候系统就会把基本成员的内存空间分配了,为什么 还要给指针重新分配一个内存空间呢?那是因为指针变量没有地方放呀!原来分配的地址是保存指针变量地址的。所以这里 如果不给成员的指针分配地址,恐怕又要乱指咯!结论:结构体指针变量:结构体名就是首地址,结构体名指针变量是首地 址保存的指针地址。结构体变量:结构体名的地址就是首地址。(主要理解怎样分配的) 
4.结构体内的成员指针变量或者结构体指针变量是不是可以不初始化,如果要应该怎样初始化 
这个吧!有点重复了,说重点:只要是指针就必须对其指向地址进行初始化,不然真会乱指!没有地址就给个NULL。 
5.结构体指针变量与结构体变量怎样引用结构体成员变量的 
这个看了上面的程序就知道了,前者用的是->,后者用的是. 
6.结构体与结构体指针用于怎样用于实参与形参的传递 
这个问题要分析是要传递实参的值,还是要修改实参的值,我这里举例都是要修改实参的值,传递地址就ok了,如果不修改 实参的值,那么传递值就好了. 
7.结构体定义过后就给结构体中的变量分配内存还是等待malloc分配呢 
这个问题在第三个问题中有提及的。当定义一个结构体指针变量的时候,只是给这个指针分配一段内存,只有用了malloc的 时候才分配内存;但是定义一个结构体变量的时候就给整个结构体分配了内存对于结构体指针分配内存,有人有一个疑问.就 是为啥结构体指针分配了内存,还要给结构体内部的成员指针变量分配内存,对于这个问题,我们观察S与&S.bottom还有S.bottom就可以分析到了。其实我们给结构体指针变量分配内存是给成员指针的地址分配内存,而我们对成员指针初始化时对指针变 量分配内存,这样理解就ok咯! 


看完这些有什么感想呢?指针,从这个指到那个,从那个再指到那那个,再从那那个指到那那那.....那个!就是这样了... 这里就不做其他指针的分析了,后续我来说***************.......******p(n级指针的理解),还有么么哒函数指针、指针函数....... 

猜你喜欢

转载自blog.csdn.net/qfc8930858/article/details/81155621