所谓动态内存分配(Dynamic Memory
Allocation)就是指在程序执行的过程中动态地分配或者回收存储空间的分配内存的方法。动态内存分配不象数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。凡是在程序中用到系统提供的动态分配存储空间函,均要求包含头文件<malloc.h>。
Malloc 向系统申请分配size字节的存储区。返回分配内存空间的起始地址,若分配失败,则返回0,类型是 void*
(或chaar*)、malloc(size)、unsigned size类型。void* 表示未确定类型的指针,void
*可以指向任何类型的数据,更明确的说是指申请内存空间时还不知道用户是用这段空间来存储什么类型的数据(比如是char还是int或者...)。C,C++规定,void*
类型可以强制转换为任何其它类型的指针。
1、为什么需要动态分配内存
首先介绍一下传统数组的缺点,这里的传统数组也叫静态数组,传统数组的缺点:
1>.数组长度必须事先定制,切只能是长整形,不能是变量;
2>.传统形式定义的数组,该数组的内存程序员无法手动释放;
3>.数组的长度一旦定义,其长度无法更改;
4>.传统形式定义数组不能跨函数使用。
以上传统数组的四点缺陷,动态数组能够很好的解决这四个缺陷,所以我们需要动态分配内存。
2、malloc的使用:
malloc是memory(内存) allocate(分配)的缩写
#include<stdio.h>
#include<maiioc.h> //使用动态分配空间函数,必须添加malloc.h头文件
int main(void)
{
int i=5;
//分配了4个字节 静态分配
int * p=(int
*)malloc(4); //12行
/*1、要使用malloc函数,必须添加malloc.h头文件
2、malloc函数只有一个形参,并且形参是整数
3、4表示请求系统为本程序分配4个字节
4、malloc函数只能返回第一个字节的地址
5、12行分配了8个字节,p变量占4个字节,p所指向的内存也占4个字节
6、p本身所占的内存是静态分配的,p所指向的内存是动态分配的
*/
* p=5; //*p代表的就是一个int变量,只不过*p这个整形变量的内存的分配方式与(int
i=5)的i的分配方式不同。
free(p); //free(p)表示把p所指向的内存给释放掉,p本身的内存是静态的,不能有程序员手动释放,p本身的内存只能在p变量所在的函数运行终止后有系统自动释放。
printf("How are you!\n");
return 0;
}
3、动态内存分配举例
#include<stdio.h>
#include<malloc.h>
int
main(void)
{
int a[5]; //如果int占四个字节的话,则本数组总共包含20个字节,每个字节被当做了一个int变量来使用
int len;
int * pArr;
int i;
//动态的构造一维数组名
printf("请输入你要存放的元素个数:");
scanf("%d",&len);
pArr=(int *)malloc(4 * len); /*本行动态的构造了一个一维数组,该数组的长度是len,该数组的数组名是pArr,
该数组的每个元素师int类型,类似于int
pArr[len];*/
//对一维数组名进行操作。如:对动态一维数组进行赋值
for(i=0;i<len;++i)
scanf("%d",&pArr[i]);
//对一维数组进行输出
printf("一维数组的内容是:\n");
for(i=0;i<len;++i)
printf("%d\n",pArr[i]);
free(pArr); //释放掉动态分配的数组
return 0;
}
4、动态数组的构造
5、free(p)的使用
表示把p所指向的内存释放掉,p本身的内存是静态的,不能有程序员释放掉,p本身的内存只能在p变量所在的函数运行终止后有系统释放。
6、静态、动态内存分配比较
1). 静态内存分配是在编译时完成的,不需要占用CPU资源;动态分配内存是在运行时完成的,动态内存的分配与释放需要占用CPU资源;
2)
.静态内存分配是在栈上分配的,动态内存是堆上分配的;
3) .动态内存分配需要指针或引用数据类型的支持,而静态内存分配不需要;
4)
.静态分配内存需要在编译前确定内存块的大小,而动态分配内存不需要编译前确定内存大小,根据运行时环境确定需要的内存块大小,按照需要分配内存即可。可以这么说,静态内存分配是按计划分配,而动态内存分配是按需分配。
5)
.静态分配内存是把内存的控制权交给了编译器,而动态内存是把内存的控制权交给了程序员;
综上所述,静态分配内存适合于编译时就已经可以确定需要占用内存多少的情况,而在编译时不能确定内存需求量时可使用动态分配内存;但静态分配内存的运行效率要比动态分配内存的效率要高,因为动态内存分配与释放需要额外的开销;动态内存管理水平严重依赖于程序员的水平,如果处理不当容易造成内存泄漏。
7、如何选择内存分配方式
1>. 全局变量尽可能不要动态分配内存。
2>. 动态分配内存时,分配与释放的代码要对称。
3>. 对动态创建的对象或分配的内存块一定要检查期有效性。
4>. 尽可能少次数地使用动态内存分配。
5>. 在保证资源利用率的前提下,能用静态内存分配不用动态分配,特别是局部临时对象。
总结:静态内存是有系统自动分配的,由系统自动释放,静态内存是在栈分配的;动态内存是由程序员分配的,手动释放,动态内存是在堆分配的。
8、跨函数使用内存的问题
1>.静态变量不能跨函数使用内存
/* 此代码是错误的,目的是为了演示静态变量不能跨函数使用静态内存由系统分配,当函数执行完毕由系统自动释放 */
# include <stdio.h>
# include <stdlib.h>
void f(int ** q)
{
/*q是指针变量,无论是什么类型的指针变量都只占4个字节 q=&p。q存放了p的地址 q存放的是int *类型的变量地址,q变量的类型是int **,*q的类型是int *。p存放的是int类型的变量地址,p变量的类型是int *,*P的类型是int。*q等价于p, p可以存放int类型变量的地址 */
int i=5;
*q=&i; //等价于p=&i
}
int main (void )
{
int * p;
f(&p);
/* f函数中的q变量和i变量的空间都是由系统分配的静态内存空间
属于静态变量,当f函数执行完毕后,系统自动释放
q和i所占用的内存空间,所以下面一行语句将无法访问
其数据。
*/
printf("%d", *p); //本语句语法上没有问题,但逻辑上有问题
system("pause");
return 0;
}
2>.动态内存可以跨函数使用内存
/* 动态内存由程序员手动分配,手动释放 */
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
void f(int ** q) //q存放int *类型变量的地址
{
//sizeof(数据类型)返回的是该数据类型所占的字节数。
//此处最好不要写成4,因为不同的机器它的数据类型所占的字节数有可能不相同
*q=(int *) malloc(sizeof(int)); //等价于p=(int *) malloc(sizeof(int));
//q=5; //error
//*q=5;//error p=5
**q=5; //*p=5
}
int main(void)
{
int * p; //p存放int *类型变量的地址
f(&p);
printf("%d\n",*p);
system("pause");
return 0;
}
// 动态内存由程序员手动分配,手动释放
#include
<stdio.h>
#include <malloc.h>
#include
<stdlib.h>
void f(int ** q) //q存放int
*类型变量的地址
{
//sizeof(数据类型)返回的是该数据类型所占的字节数。
//此处最好不要写成4,因为不同的机器它的数据类型所占的字节数有可能不相同
*q=(int
*) malloc(sizeof(int)); //等价于p=(int *)
malloc(sizeof(int));
//q=5;//error
//*q=5;//error
p=5
**q=5; //*p=5
}
int main(void)
{
int
* p; //p存放int
*类型变量的地址
f(&p);
printf("%d\n",*p);
system("pause");
return
0;
}
http://wljjiwang.blog.163.com/blog/static/54762512201422724922388/
跨函数使用内存空间