动态内存分配【重点】

动态内存分配【重点难点】

传统数组的缺点:

1、数组长度必须事先制定,且只能是常数,不能是变量
例子:
int a[5]; //OK int len = 5; int a[len]; //error

2、传统形式定义的数组,该数组的内存程序员无法手动释放
在一个函数运行期间,系统为该函数中数组所分配的空间会一直存在,直到该函数运行完毕时,数组的空间才会被系统释放

3、数组的长度一旦定义,其长度就不能再改变 数组的长度不能在函数运行的过程中动态的扩充或缩小

4、A函数定义的数组在A函数运行期间可以被其他函数使用,但A函数运行完毕之后,A函数中的数组将无法再被其他函数使用
传统方式定义的数组不能跨函数使用

为什么需要动态分配内存?

动态数组很好地解决了传统数组这四个缺点

传统数组也叫静态数组

动态内存分配举例——动态数组的构造【难点】

malloc 函数的使用(两个程序讲解)

/* 
	Date: 20/04/22 16:42
	Description: 该程序没有实际含义 
	malloc 函数是 memory(内存) allocate(分配) 的缩写  
*/
# include <stdio.h>
# include <malloc.h>

int main (void)
{
	int i = 5; // 分配了 4 个字节  静态分配
	int *p = (int *) malloc (4);  //强制类型转换   指针变量本身占4个字节 
	          /*
			    1、要使用 malloc 函数,必须添加 malloc.h 头文件 
			    2、malloc 函数只有一个形参,并且形参是整型
				3、malloc(4) 中的 4 表示请求系统为本程序分配四个字节
				4、malloc函数只能返回第一个字节的地址,  
			    5、12行分配了 8 个字节,p 变量占4个字节,p指向的内存也占四个字节
				6、p本身所占的内存是静态分配的,p所指向的内存是动态分配的 
			  */ 
	
	*p = 5;  // *p 代表的就是一个 int 变量,只不过 *p这个整型变量的内存分配方式和 11行整型变量 i 的内存分配方式不同 
	free(p); //表示把 p 所指向的内存给释放掉  p 本身的内存是静态的,不能由程序员手动释放,只能在p变量所在的函数运行完毕后由系统释放 
	printf("hhh!\n"); 
	
	
	return 0;
 }
/*
	Date: 20/04/22 17:17
	Description:  malloc 的用法 
*/
# include <stdio.h>
# include <malloc.h>

void f(int *q)   // q 是 p 的一份拷贝 
{
//    *p = 200;  //error
//    q = 200;   //eooor
//   **q = 200;  //error   只有指针变量前面才能加 *,  
 	 *q = 200; 
//	free(q); // 把 q 指向的内存释放掉 ,该语句必须注释掉,否则会导致第23行的代码出错 
}

void g(int ** p)
{
	**p = 300; 
 } 
int main (void)
{
	int *p = (int *)malloc(sizeof(int));  //  23 行  sizeof(int)返回值是 int 所占的字节数 
	*p = 10;
	printf("%d\n",*p);   // 10
	
	f(p);     // p 是 int * 类型
	printf("%d\n",*p);     //200 
	
	g(&p);   // p 是 int * 类型,&p 是 int ** 类型 
	printf("&p = %d\n",*p); 
	
	return 0;
 } 

/*
在DEVC++中输出的结果是
--------------------------------- 
10
200
&p = 300

--------------------------------

*/ 

构造动态一维数组(一个程序讲解)

/* 
	Date: 20/04/22 17:45
	Description: 动态一维数组 
	        
*/
# include <stdio.h>
# include <malloc.h>
int main (void)
{
	int a[5];  //如果int占 4个字节的话,则本数组总共包含有 20个字节,每4个字节被当作一个int变量来使用 
	int len;
	int * pArr;
	int i;
	
	// 动态的构造一维数组 
	printf("请输入你要存放的元素的个数:"); 
	scanf("%d",&len);
	pArr = (int *)malloc(4 * len);  // 相当于 int pArr[len]  本行动态地构造了一个一维数组,该数组的长度是 len,数组类型是 int,数组名是 pArr, 
	
	//对一维数组进行操作      如:对动态一维数组进行输出 
	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;
 } 

静态内存和动态内存的比较

静态内存由系统自动分配,由系统自动释放
静态内存是在栈中分配的

动态内存是由程序员手动分配,手动释放(不释放会造成内存泄漏)
动态内存是在堆分配的

【栈和堆的概念具体可参见数据结构】

跨函数使用内存的问题【难点】

预备知识:多级指针的使用【详见指针的用法】

静态变量不能跨函数使用详解【重点】 (一个程序讲解)

/*
	Date: 20/04/23 13:03
	Description: 静态变量不能跨函数使用  静态内存是在栈里分配的,出栈之后就不能使用了 
	             该程序并没有实际含义 
*/
# include <stdio.h>

void f(int **q)  // q也是个指针变量,无论q是什么类型的指针变量,都只占4个字节 
{
	int i = 5;
//  *q 等价于 p    q 和 **q 都不等价于 p
//  *q = i;   // error 因为*q = i; 等价于 p = i; 这样写是错误的
     *q = &i;   // p = &i 
}

int main (void)
{
	int *p;
	
	f(&p);
	printf("%d\n",*p);   //本程序语法没有问题,但是逻辑上有问题 (内存越界) 
	
	return 0;
}

动态变量可以跨函数使用详解【重点】 (一个程序讲解)

/*
	Date: 20/04/23 18:47
	Description: 动态内存是在堆里分配的,出栈不出栈没有影响 
*/
# include <stdio.h>
# include <malloc.h>

void f( int **q )
{
	*q = (int *)malloc(sizeof(int)); // sizeof(数据类型) 返回值是该数据类型所占的字节数 
	           //等价于 p = (int *)malloc(sizeof(int));
//	q = 5;     // error 
//	*q = 5;   // p = 5;   p里面只能存地址 
	**q = 5;  // *p = 5
}

int main (void)
{
	int * p;
	
	f(&p);
	printf("%d\n",*p);
	return 0;
 } 
posted @ 2020-04-23 21:04  柯星  阅读(5)  评论(0编辑  收藏  举报  来源