欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C语言学习之动态内存分配的四个函数

程序员文章站 2022-04-15 21:01:16
前面中我们了解到: int n; int arr[n]; 这样定义数组是不可取的,不能用此方法给数组分配动态内存,那怎么样才能实现这种可能呢? 接下来我将关于动态内存的知识做以下总结。 有关动态内存...

前面中我们了解到:

int n;

int arr[n];

这样定义数组是不可取的,不能用此方法给数组分配动态内存,那怎么样才能实现这种可能呢?

接下来我将关于动态内存的知识做以下总结。

有关动态内存的函数有四个,分别是malloc( )、calloc( )、free( )、realloc( )。ansi(美国国家标准协会)标准建议应添加头文件#include ,但许多c编译要求用#include 头文件,在使用时应注意。

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.栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收。

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