C语言学习笔记——指针:动态内存分配

C程序的内存映像
C程序的变量内存分配有三种:
(1)从静态存储区分配:程序的全局变量和静态变量都在静态存储区上分配,且在程序编译时就已经分配好了,在程序运行期间都是存在的。只有在程序终止前,才被操作系统收回。
(2)在栈上分配:在执行函数调用时,函数内的局部变量及形参都是在栈上分配的,该函数执行结束时,这些内存被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是容量有限。
(3)从堆上分配:在程序运行期间,用动态内存分配函数来申请的内存都是从堆上分配的。动态内存的生存期由程序员自己来决定,使用非常灵活,但最容易出问题。一定要注意在这些内存不用时,一定用free()将其释放,以防止发生内存泄漏。
C语言学习笔记——指针:动态内存分配_第1张图片
函数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
#include
#include
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语言大学实用教程

你可能感兴趣的:(C/C++)