内存静态存储区(static):全局变量、静态变量(static int a;)
内存动态存储区(栈stack):局部变量
内存自由存储区(堆heap):临时用数据
其中静态存储区、动态存储区的变量空间开辟和释放自动进行,不需要程序人员操作内存;
只有堆区需要手动开辟和释放空间:静态开辟——在编译时刻,数组的空间大小就开辟完成;
动态开辟——malloc、calloc、realloc;手动释放空间free
void *malloc(unsigned int size); 开辟size大小数目的字节空间
void *calloc(unsigned n,unsigned size); 开辟n个字节块大小为size的内存空间
void *realloc(void *p,unsigned int size); 第一次p指针开辟长度不够,重新选址开辟size大小数目的字节空间
malloc
#include
#include
int main()
{
int n;
printf("input n:>");
scanf("%d",&n);
int *p=(int *)malloc(sizeof(int)*n); //申请开辟空间
if(NULL==p)
{
printf("malloc memory fail!\n");
exit(1); //检查malloc开辟空间是否成功,失败p无指向退出程序
}
for(int i=0;i
calloc
#include
#include
int main()
{
int n;
printf("input n:>");
scanf("%d",&n);
int *p=(int *)calloc(n,sizeof(int)); //申请开辟n块大小为sizeof(int)个字节的空间
if(NULL==p)
{
printf("malloc memory fail!\n");
exit(1); //检查malloc开辟空间是否成功,失败p无指向退出程序
}
for(int i=0;i
realloc
#include
#include
void main()
{
int *p=(int *)malloc(sizeof(int)*5);
if(NULL==p)
{
printf("malloc memory fail!\n");
exit(1);
}
for(int i=0;i<5;++i)
{
p[i]=i+1;
}
//起初申请的5个空间不够用
p=(int *)realloc(p,sizeof(int)*10);
//realloc对p所指的原始空间进行开辟,但开辟空间前后p所指的内存地址不一定一样
//把原来的5个扩展为10个,用原来的指针p接收realloc的返回值,如果没有接收指针p,会丢失先前空间的值
if(NULL==p)
{
printf("malloc memory fail!\n");
exit(1);
}
for(i=5;i<10;++i)
{
p[i]=i+1;
}
for(i=0;i<10;++i)
{
printf("%d",p[i]);
}
system("PAUSE");
}
realloc对p所指的原始空间进行开辟,但开辟空间前后p所指的内存地址不一定一样
把原来的5个扩展为10个,用原来的指针p接收realloc的返回值,如果没有接收指针p,会丢失先前空间的值
第一次申请空间在内存里有个位置,第二次申请空间时,会检查内存里其后的空间大小是否满足申请大小:
如果满足,可以不修改第一次p的指向,连续地在其后开辟空间
如果不满足,要在内存中寻找满足大小的空间,如果找不到就开辟失败NULL,找到了就返回该空间的地址,并存放值
自定义函数模拟分析realloc过程,还原第一次被开辟空间被free释放过程
#include
#include
#include
//模拟realloc开辟空间过程自定义函数my_realloc,第一次被开辟空间free释放
void* my_realloc(void *p,size_t size) //size_t的类型在底层是无符号整型
{
void *new_p=malloc(size);
if(NULL==new_p)
{
printf("malloc memory fail!\n");
exit(1);
}
memcpy(new_p,p,size); //内存拷贝函数,将p指针空间的size个元素拷贝给new_p指针空间
free(p); //释放第一次开辟的空间
p=new_p; //把新开辟空间地址赋值给第一次开辟空间定义的指针变量p
return p;
}
void main()
{
int *p=(int *)malloc(sizeof(int)*5);
if(NULL==p)
{
printf("malloc memory fail!\n");
exit(1);
}
for(int i=0;i<5;++i)
{
p[i]=i+1;
}
//起初申请的5个空间不够用,自定义my_realloc重新拷贝函数
p=(int *)my_realloc(p,sizeof(int)*10);
if(NULL==p)
{
printf("malloc memory fail!\n");
exit(1);
}
for(i=5;i<10;++i)
{
p[i]=i+1;
}
for(i=0;i<10;++i)
{
printf("%d",p[i]);
}
system("PAUSE");
}
void类型指针是“指向空类型”或“不指向确定的类型”的数据
注意melloc、alloc、realloc函数原本返回值类型就是void型指针,所以要想给真实类型指针赋值,需要进行强制类型转换
#include
#include
void main()
{
int a=10;
double d=12.34;
int *p=(int *)&d; //强制指针类型转换才能进行赋值
void *pv=&a; //void泛型指针
pv=&d; //void型指针可以接收一切类型地址
//但由于其类型未知无法为其开辟空间,不能进行pv++操作
int *pa=(int *)pv; //也不能用void型指针给确定类型指针赋值
//void类型不能转换成真实类型,需要强制类型转换才能赋值
}