C语言----动态内存分配四函数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_41026740/article/details/79751564

前面中我们了解到:
int n;

int arr[n];

这样定义数组是不可取的,不能用此方法给数组分配动态内存,那怎么样才能实现这种可能呢?
接下来我将关于动态内存的知识做以下总结。


有关动态内存的函数有四个,分别是malloc( )、calloc( )、free( )、realloc( )。ANSI(美国国家标准协会)标准建议应添加头文件#include <stdlib.h>,但许多C编译系统要求用#include <malloc.h>头文件,在使用时应注意。
ANSI标准要求动态分配系统返回void指针。 void指针具有一般性,它们可以指向任何类型的数据。所以有时需要用到强制类型转换的方法把void指针转化为所需的类型。

一、动态内存函数

(一)malloc函数
功能:申请动态内存,分配size字节的存储区
所需参数:一个参数size,表示所分配的字节
形如:int *p = (int *)malloc(n*sizeof(int));
返回值:所分配的内存区起始地址,如内存不够,返回0


(二)calloc函数
功能:分配n个数据项的内存连续空间,每个数据项的大小为size
所需参数:两个参数
形如:int *p = (int *)calloc(n,sizeof(int));

用malloc函数表示如下:

int main()
{
 int n = 10;
/*  int *p = (int *)malloc(n*sizeof(int));
 for(int i=0;i<10;i++)
 {
  p[i] = 0;
 } */    //等同calloc
 //int *p = (int *)calloc(n,sizeof(int));//0

返回值:分配内存单元的起始地址,如不成功,返回0


malloc函数与calloc函数的区别:
malloc申请后空间的值是随机的,并没有进行初始化,而calloc却在申请后,对空间逐一进行初始化,并设置值为0。


(三)free函数
功能:释放p所指的内存区

所需参数:一个参数

形如:free(p);   // 释放内存,与malloc配合使用
返回值:无

(四)realloc函数
功能:将p所指出的已分配内存区的大小改为size,size可以比原来分配的空间大,即扩容
所需参数:两个参数,新的大小,以字节为单位

    int n = 10;    
    int *p = (int *)malloc(n*sizeof(int));
	int i;
	for(i=0;i<10;i++)   //模拟p已经被使用
	{
		p[i] = i*i + i;
	}
将以上10 个内存扩大为20个内存,如下:
    int n = 20;
    int *q = (int *)malloc(20*sizeof(int));
	for(i=0;i<10;i++)
	{
		q[i] = p[i];
	}
	free(p);
	p = q;
	q = NULL;  // 把q注销掉,若无此句,则崩溃
	//上面的代码等同于realloc
等同于:p = (int *)realloc(p,80);


一般情况下,操作系统会忽略缩小内存的要求,操作系统会缓存刚刚保存的数据,提高代码的利用率和运行速度。
动态内存存储里,不讨论堆中谁的内存大谁的内处小,不能确定地址的大小规律,有存储空间就有可能保存新数据。
二、free( )崩溃的原因
动态里每个块前有个头,每个块后有个尾。(边界标识法)
头:开启  
尾:合并(胶水的作用),可以把小块拼成大块


1、越界(修改了尾信息)
2、指针移动(如*p = 0;p++)
3、重复释放(free至少两次)
4、释放栈内存(数组不能释放,堆却可以,栈内存操作系统会自动回收)

四、堆与栈的区别:
栈:一使用就会释放内存,1M
堆:申请的内存大,但不会主动释放,容易发生内存泄漏。

            1.栈内存存储的是局部变量而堆内存存储的是实体;

            2.栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短;

            3.栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收。

五、动态内存最严重的问题就是:内存泄漏,还有数组越界。



猜你喜欢

转载自blog.csdn.net/qq_41026740/article/details/79751564
今日推荐