C语言中的全局变量和局部变量分别分配内存的栈(stack) 中的静态存储区和动态存储区,关于静态存储区和动态存储区之前的博客也有介绍(https://blog.csdn.net/wuyuzun/article/details/82354885)
在括号里的这篇博文里介绍过静态存储区和动态存储区内的变量是有生命周期的;全局变量被编译器编译时,开始分配其内存单元,生命周期持续到程序运行结束;局部变量比如函数参数,当程序被调用时为参数分配内存单元,函数调用结束生命周期也结束,所占用的内存单元被释放;那么除此之外还有一种情况,就是生命周期由用户自己决定,需要多少内存就开辟多少内存,用完了的时候释放就可以了,并且这些内存一般是用来存储一些临时数据,所以称为内存的动态分配,而这个存储区成为堆(heap);
所以将C语言中常用的存储区分类:
区名 | 生命周期 | 存储数据类型 |
---|---|---|
静态存储区 | 从定义处到程序结束 | 全局变量,静态变量(static) |
文字常量区 | 从定义处程序结束释放 | 常量字符串 |
程序代码区 | 从开始执行程序的开始 ,到程序结束 | 二进制代码 |
栈(stack) | 一般为函数结束 | 函数参数值,临时变量,局部变 |
堆(heap) | 由程序猿开辟,由程序猿释放或程序结束释放 | 内存的动态存储区,存放程序运行中的临时数据 |
注意:内存的动态分配是向系统申请内存空间,但是由于这个内存空间不像数组一样有数组名,所以对这段内存的读写都是靠指针来实现的;
系统提供的库函数:
函数名 | 全称 | 功能 |
---|---|---|
malloc(n) | 动态内存分配函数 | 在堆总开辟n个字节的存储空间 |
calloc(n,m) | 动态内存分配并清零函数 | 在堆中开辟n*m个字节空间(),为每个元素清零 |
free§ | 动态内存释放函数 | 释放指针p所指向的开辟的内存空间 |
realloc(p,n) | 动态内存调整函数 | 修改p所指向的动态内存空间为n个字节(p的值不变) |
**注意:**这些函数定义在库函数stdlib.h中,在使用时需要调用其头文件;
函数原型:void *malloc(unsigned int size);
函数特点:
#include
#include
void main()
{
void *p = NULL;
p = malloc(100);
printf("%d\n",p);
}
运行结果:(这个地址是随机的,每次运行结果并不相同)
图像表示"p = malloc(100)":
函数原型:void *calloc(unsigned int n , unsigned int size);
函数特点:
举例:
#include
#include
void main()
{
void *p = NULL;
p = calloc(4,100); //在栈中分配4个长度为100字节的内存空间;
printf("%d\n",p);
}
运行结果:(这个地址是随机的,每次运行结果并不相同)
图片解释“p = calloc(4,100)”:
函数原型:void free(void *p);
函数特点:
举例说明:
#include
#include
void main()
{
void *p = NULL;
p = malloc(4,100);
printf("%d\n",p);
free(p); //需要注意的是,内存释放后,p本身的值并没有发生改变;
}
函数原型:void *realloc(void *p,unsigned int size)
函数特点:
举例:
#include
#include
void main()
{
void *p = NULL;
p = malloc(100);
realloc(p,120);
printf("%d\n",p);
free(p);
}
运行结果:(这个地址是随机的,每次运行结果并不相同)
图片解释“realloc(p,120)”:
但是realloc函数不仅可以增加拓展内存空间,还可以缩短内存空间;
例如:realloc(p,80)代表:
注意:
用来存临时数据, 而且是一般存储的数据往往都是有一定量的,但是这里有个问题:分配的临时存储空间内并没有数据类型,例如malloc开辟的空间,就只是一个由若干个字节组成的内存空间块,如何像数组一样去存储数据,并按照地址去访问它们?解决这个问题的办法是强制类型转换;并且有一点要说明的是,在C 99之前,malloc和calloc函数的数据类型是字符指针型(char *)的,但即使是这样,这些内存空间并不一定是用来存字符的;
举例说明:
#include
#include
void main()
{
void Chack(int *p);
int i,*p = NULL;
p = (int *) malloc(5*sizeof(int));
/*
1.这里发生了强制性类型转化,但即使不进行强制转化,编译器也会进行默认转化
2.sizeof()函数解决了程序的健壮性和可已知项以及所开辟空间字节数和所转化数据类型的不匹配问题;
*/
printf("请输入5个人的成绩:\n");
for(i=0;i<5;i++)
scanf("%d",p+i);
Chack(p);
free(p);
}
void Chack(int *p)
{
int i=0;
for(;i<5;i++)
if(p[i]<60)
printf("不合格的成绩有:%d\n",p[i]);
}
运行结果:
图片解释:“p = (int ) malloc(5sizeof(int)); ”
显然,所开辟的空间被转换成了数组一样的内存空间,并存储了数据,各个小存储区可以利用指针的算术运算存取;
写博客途中有遇到一些问题,拜读过这位前辈的博客,写的很好,很有深度:
https://blog.csdn.net/shuaishuai80/article/details/6140979