目录
一:栈区
堆区:程序员分配释放
栈区:系统分配释放
系统分配释放的内存空间 属于栈区 示例如下
1.main.c
#include<stdio.h>
#include"menu.h"
int main()
{
//创建结构体指针
MENU_T *pmenu = NULL;
MENU_T menu ={1001,"沙茶面",18.8};
//pmenu = &menu;//赋值(系统分配的内存空间)
printf("%d\n",sizeof(MENU_T));//32
return 0;
}
#ifndef MENU_H
#define MENU_H
typedef struct menu_t//菜谱结构体
{
int menu_id;//序号
char name[20];//菜名
double price;//价格
}MENU_T;
#endif
二:堆区
void *作为函数返回的好处:可以强制转化为任意类型的指针【通用性】
malloc动态开辟内存空间,由程序员手动分配释放,属于堆区
开空间是否成功,NULL判断 ,示例如下
main.c
#include<stdio.h>
#include"menu.h"
int main()
{
//创建结构体指针
MENU_T *pmenu = NULL;
//动态开空间
pmenu = (MENU_T *)malloc(sizeof(MENU_T)); //强制转化
printf("111\n");//111
//开空间是否成功
if(pmenu==NULL)
{
printf("open space fail\n");
exit(0);//程序退出
}
printf("open space success\n");//open space success
return 0;
}
三:开空间后需要释放内存空间
具体实现步骤
1.创建结构体指针
2.动态开空间,开空间是否成功
3.内存的初始化
4.对创建好的内存空间进行操作
5.程序员手动释放内存空间
示例如下:
#include<stdio.h>
#include"menu.h"
#include<stdlib.h>//memset
#include<string.h>//strcpy
int main()
{
//创建结构体指针
MENU_T *pmenu = NULL;
//动态开空间
pmenu = (MENU_T *)malloc(sizeof(MENU_T)); //强制转化
printf("111\n");//111
//开空间是否成功
if(pmenu==NULL)
{
printf("open space fail\n");
exit(0);
}
printf("open space success\n");//open space success
//内存的初始化 把指针首地址从此地址后多少字节赋值0 空字符串
memset(pmenu,'\0',sizeof(MENU_T));
//操作+数据的存储 结构体指针访问属性:结构体指针->属性名
//操作创建的内存空间
pmenu->menu_id = 1002;
strcpy(pmenu->name,"黄焖鸡");//字符串赋值 strcpy
pmenu->price=16.5;
//程序员手动释放内存
free(pmenu); //释放由指针指向的内存 释放后数据清空归还系统
printf("222\n");//222
return 0;
}
四:malloc 开辟多块空间
malloc开辟多块内存空间,示例如下
#include<stdio.h>
#include"menu.h"
#include<stdlib.h>//memset
#include<string.h>//strcpy
int main()
{
//连续开3块
//创建结构体指针
MENU_T *pmenu = NULL;
//动态开空间
pmenu = (MENU_T *)malloc(sizeof(MENU_T)*3);
//开空间是否成功
if(pmenu==NULL)
{
printf("open space fail\n");
exit(0);
}
//内存的初始化
memset(pmenu,'\0',sizeof(MENU_T)*3);
//赋值
pmenu->menu_id = 1002;
strcpy(pmenu->name,"黄焖鸡");//字符串赋值 strcpy
pmenu->price=16.5;
(pmenu+1)->menu_id = 1003;
strcpy((pmenu+1)->name,"麻辣烫");//字符串赋值 strcpy
(pmenu+1)->price=25.8;
(pmenu+2)->menu_id = 1004;
strcpy((pmenu+2)->name,"酸辣粉");//字符串赋值 strcpy
(pmenu+2)->price=38.8;
//释放
free(pmenu);//释放后所有内存空间都随机值了
return 0;
}
五:calloc & malloc
malloc在开辟空间后,需要初始化为0
calloc在开辟空间的同时,就会初始化为0
如下示例:
pmenu = (MENU_T *)malloc(sizeof(MENU_T)*3); //开空间但初始化随机值
pmenu=(MENU_T *)calloc(3,sizeof(MENU_T)); //开空间同时初始化为0
calloc一句相当于malloc两句
pmenu=(MENU_T *)calloc(3,sizeof(MENU_T)); //开空间并且初始化为0
//这一句相当于下面两句:
pmenu = (MENU_T *)malloc(sizeof(MENU_T)*3); //开空间但初始化为随机值
memset(pmenu,'\0',sizeof(MENU_T)*3);//初始化为0 空字符串
对realloc的了解,示例如下
realloc(pmenu,sizeof(MENU_T));//释放最后一块结构体空间 变随机值
realloc(pmenu,0); //相当于free 释放全部内存 都随机值
六:链表的学习【以菜谱结构体为例】
#ifndef MENU_H
#define MENU_H
typedef struct menu_t
{
int menu_id;
char name[20];
double price;
struct menu_t *pnext;//指针 指向下个结构体存储的地址
}MENU_T;
//初始化链表头
MENU_T *menuList_init();
//把结构体添加到链表的尾部
void menuList_add(MENU_T *head,MENU_T menu);
//统计链表的节点个数
int menuList_count(MENU_T *head);
#endif
#include"menu.h"
#include<stdlib.h>
//初始化链表头
MENU_T *menuList_init()
{
//创建菜谱结构体指针变量
MENU_T *head = NULL;
//动态开空间
head = (MENU_T *)malloc(sizeof(MENU_T));
if(head == NULL)
{
printf("open fail\n");
exit(0);
}
//初始化 数据域
memset(head,'\0',sizeof(MENU_T));
//初始化指针域
head->pnext = NULL;
return head;
}
//把结构体添加到链表的尾部
void menuList_add(MENU_T *head,MENU_T menu)
{
MENU_T *tmp=head;
MENU_T *pNewNode = NULL; //新节点
//判断pnext是否为空 找到链表的尾部
while(tmp->pnext!=NULL)
{
tmp=tmp->pnext;
}
//动态开空间
pNewNode = (MENU_T *)malloc(sizeof(MENU_T));
if(pNewNode==NULL)
{
printf("open fail\n");
exit(0);
}
//初始化 数据域
memset(pNewNode,'\0',sizeof(MENU_T));
//数据域赋值
memcpy(pNewNode,&menu,sizeof(MENU_T));
//新节点连接到上一个节点的指针域
tmp->pnext = pNewNode;
}
//统计链表的节点个数
int menuList_count(MENU_T *head)
{
//每一个节点找pnext 判断一下是否为空
//不为空 +1
int count =0;
MENU_T *tmp=head;
while(tmp->pnext!=NULL)
{
count++;
tmp=tmp->pnext;
}
return count;
}
3.main.c
a.创建链表头
#include<stdio.h>
#include"menu.h"
void demo3_createList();
int main()
{
demo3_createList();
return 0;
}
void demo3_createList()
{
//创建结构体指针
MENU_T *head = NULL;
head = menuList_init();
printf("创建链表头成功!\n");//创建链表头成功!
}
b.添加节点到链表尾部
#include<stdio.h>
#include"menu.h"
void demo3_createList();
int main()
{
demo3_createList();
return 0;
}
void demo3_createList()
{
//创建结构体指针
MENU_T *head = NULL;
MENU_T menu1 ={1001,"沙茶面",18.8};
MENU_T menu2 ={1002,"黄焖鸡",16.8};
MENU_T menu3 ={1002,"酸辣粉",38.8};
head = menuList_init();
printf("创建链表头成功!\n");//创建链表头成功!
//把我们定义的结构体按顺序添加到链表头的后面
menuList_add(head,menu1);
menuList_add(head,menu2);
menuList_add(head,menu3);
}
c.统计链表的节点个数
#include<stdio.h>
#include"menu.h"
#include<stdlib.h>//memset
#include<string.h>//strcpy
void demo3_createList();
int main()
{
demo3_createList();
return 0;
}
void demo3_createList()
{
int count =0;
//创建结构体指针
MENU_T *head = NULL;
MENU_T menu1 ={1001,"沙茶面",18.8};
MENU_T menu2 ={1002,"黄焖鸡",16.8};
MENU_T menu3 ={1002,"酸辣粉",38.8};
head = menuList_init();
printf("创建链表头成功!\n");//创建链表头成功!
//把我们定义的结构体按顺序添加到链表头的后面
menuList_add(head,menu1);
menuList_add(head,menu2);
menuList_add(head,menu3);
count =menuList_count(head);
printf("一共有%d个菜\n",count);//一共有3个菜
}
深层次学习链表,可参考以下文章