C程序的内存映像
C程序的变量内存分配有三种:
(1)从静态存储区分配:程序的全局变量和静态变量都在静态存储区上分配,且在程序编译时就已经分配好了,在程序运行期间都是存在的。只有在程序终止前,才被操作系统收回。
(2)在栈上分配:在执行函数调用时,函数内的局部变量及形参都是在栈上分配的,该函数执行结束时,这些内存被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是容量有限。
(3)从堆上分配:在程序运行期间,用动态内存分配函数来申请的内存都是从堆上分配的。动态内存的生存期由程序员自己来决定,使用非常灵活,但最容易出问题。一定要注意在这些内存不用时,一定用free()将其释放,以防止发生内存泄漏。
函数malloc:用于分配若干字节的内存空间,返回一个指向该存储区地址的指针。若系统不能提供足够的内存单元函数将返回空指针(NULL)。
函数malloc()的原形为:
void *malloc(unsigned int size)
其中,参数size为无符号整型数,表示向系统申请的空间大小,函数调用成功将返回一个指向void类型的指针。因此,如果将函数调用的返回值赋值给某个指针,则应先根据该指针的基类型,用强制转换将返回的指针值强制转换为所需类型,然后再进行赋值操作。例如:
int *pi=NULL;
pi = (int*)malloc(sizeof(int)); //用sizeof计算出本系统中该类型需占内存空间字节数,提高程序可移植性
函数calloc():用于给若干同一类型的数据项分配连续的存储空间,其中每个数据项的长度单位为字节。与malloc()不同的是:通过函数calloc所分配的存储单元,系统将其自动置初值为0。因此,从安全的角度而言,使用calloc()动态分配内存更明智。但是实际操作过程中,由于malloc执行效率更高,应用的更多。
函数calloc()的原形为:
void *calloc(unsigned int num,unsigned int size)
其中,第一个参数num表示向系统申请的内存空间的数量,第二个参数size表示申请的每个空间的字节数。若函数调用不成功,函数返回空指针(NULL);若函数调用成功,将返回一个void类型的连续储存空间的首地址。如果要将该地址赋给某个指针,则应先根据该指针的基类型,将返回值进行相应的类型转换,然后再进行赋值操作。例如:
float *pf=NULL;
pf = (float *)calloc(10,sizeof(float));
表示向系统申请10个连续的float类型的存储单元,并用指针pf指向该连续存储单元的首地址,系统申请的总的存储单元字节数为10*sizeof(float)。显然,用函数calloc()申请的存储单元相当于一个一维数组。
函数free():函数原型为:
void free (void*p);
该函数的功能是释放动态申请的由指针p指向的存储空间,该函数无返回值。函数free()中参数给出的地址只能是由函数malloc()和calloc()申请空间时返回的地址。
例如,为前面已申请的指向int型数据的指针pi所指向的sizeof(int)字节的储存空间释放,用下面语句:
free(pi);
函数realloc():该函数的功能是将指针p所指向的存储空间大小改为size字节,函数返回值是新分配的存储空间的首地址,与原来分配的首地址不一定相同。注意:由于动太内存分配得到存储单元没有名字,只能通过指针引用它,所以一旦改变了指针的指向,原来分配的存储单元及放于其中的数据也就随之丢失了,从而造成内存泄漏,因此,这个指针是个变量,但不要轻易改变它的值。
动态内存分配的应用例子:一维动态数组的实现
函数功能:输入一个班某学生的成绩,计算平均分,然后输出,班级人数由键盘输入。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main() {
int *p = NULL, n, i, sum;
printf("Please enter array size:");
scanf("%d", &n);//输入学生人数
p = (int*)malloc(n * sizeof(int));
if (p == NULL) { // 确保指针使用前是非空指针,当p为空指针时结束程序运行
printf("No enough memory!\n");
exit(0);
}
printf("Please enter the score:");
for (i = 0; i < n; i++) { //输入n个学生的分数
scanf("%d", p + i);
}
sum = 0;
for (i = 0; i < n; i++) {
sum = sum + *(p + i); //计算总分
}
printf("aver=%d\n", sum / n); //输出平均分
printf("p = %p\n", p); //输出指针释放前指向空间
free(p); //释放malloc()申请的内存
printf("p = %p\n", p); //输出指针释放后指向空间
p=NULL; //指针置空
return 0;
}
运行程序如下:
Please enter array size:5
Please enter the score:90 85 70 95 80
aver=84
p=00F85450
p=00F85450
由该程序运行结果可知,用free()函数释放前后,p 所指向的内存空间是一样的。所以释放后 p 所指向的的仍然是那块内存空间,那么就仍然可以往里面写数据。可是释放后该内存空间已经不属于它了,该内存空间可能会被分配给其他变量使用。如果其他变量在里面存放了值,而你现在用 p 往里面写入数据就会把那个值给覆盖,这样就会造成其他程序错误。所以当指针变量被释放后,要立刻把它的指向改为 NULL。
参考文献:C语言大学实用教程