7.【动态内存分配】

【专题】【重点】                                                                        
动态内存分配【重点 难点】                                                             
传统数组的缺点:                                                                     
1. 数组长度必须事先制定,且只能是常整数,不能是变量                              
例子:                                                                        
int a[5]; //ok                                                              
int len =5; int a[len];   //error 不能是变量                                
2. 传统形式的定义的数组,该数组的内存程序员无法手动释放它,是由系统自动释放的    
  在一个函数运行期间,系统为该函数中数组所分配的存储空间会一直存在,            
  直到该函数运行完毕时,数组的空间才会被系统释放。                              
                                                                                        
3. 数组的长度一旦定义,其长度就不能再更改 a[5] 其中5就表示数组长度               
数组的长度不能在函数运行的过程总动态的扩充或缩小                              
                                                                                        
4. A函数定义的数组,在A函数运行期间可以被其他函数使用,但A函数运行完毕之后,     
A函数中的数组将无法再被其他函数使用                                           
传统方式定义的数组,不能跨函数使用                                            
                                                                                        
为什么需要动态分配内存                                                              
动态数组很好的解决了传统数组的四个缺陷                                            
传统数组也叫静态数组                                                              
                                                                                        
动态内存分配的举例_动态数组的构造                                                   
malloc函数的使用:malloc 是分配内存的意思                                         

malloc是memory(内存) allocate(分配)的缩写

#include <stdio.h>                                                                                           
#include <malloc.h>   //不能省                                                                               
int main(void)                                                                                               
{                                                                                                            
	int i = 5;  //静态分配了 4个字节  //5行                                                                    
	int *p = (int *)malloc(4);    //6行                                                                        
		/*                                                                                                       
			1.要使用malloc函数,必须添加malloc.h的头文件                                                           
			2.malloc函数只有一个形参,并且形参是整型                                                               
			3.形参 (4) 表示请求系统为本程序分配4个字节                                                             
			4.malloc函数只能返回第一个字节的地址                                                                   
		        5.6行最终分配了8个字节,P变量占了4个字节,p所指向的内存也占了4个字节                                   
		        6.p 本身所占 的4个内存是静态分配的,p 所指向的 4个内存是动态分配的                                     
		*/                                                                                                       
	*p = 5; //*p 代表的就是一个int变量,只不过*p这个整型变量的内存分配方式和5行的分配方式不同                  
	free(p);  //表示把p所指向的内存给释放掉,p本身的内存是静态的,不能由程序员手动释放,                        
			  //p本身的内存只能在p变量所在的函数运行终止时由系统自动释放                                           
	printf("hello!\n");                                                                                        
	return 0;                                                                                                 
}                                                                                                            
解析:                                                                                                       
	(int *)是将malloc请求的字节强制转换为整型变量,按整型变量所占字节数来划分地址。                            
	(第一个字节地址只有值,而没有类型,只有强制转换后才会给加上所属转换的类型。)                             
			malloc后面的括号中必须是一个值,而这个值必须为整数,无论请求的字节数是多少,比如 malloc(200)           
					但是最终返回的都是第一个字节的地址,如果只知道第一个字节地址,但是并不知道第一个字节地址指向的变量 
					最终会占用几个字节,所以需要在前面进行强制的变量类型转换,告诉程序最后按什么标准来划分地址。以便明 
					白第一个字节地址到底指向的是一个什么类型的变量。最终表示请求来的字节数按第一个字节地址所指向的变量 
					类型所占的字节数来划分,比如(int *)是4个字节的整型变量类型,那么最后就会按4个字节来进行划分。    
					                                                                                                   
					如果按 malloc(200) 来看:                                                                          
					char *  	占1字节  200个变量                                                                       
					int * 		占4字节	 50个变量                                                                        
					double *	占8字节  25个变量                                                                        
					                                                                                                   
					int *p = (int *)malloc(4)                                                                          
					完了之后,请求来的4个字节的首地址就会给p 而通过强制类型转换,也知道了转换后的类型。                
#include <stdio.h>                                                                                                  
#include <malloc.h>                                                                                                 
void f(int *q)                                                                                                     
{                                                                                                                   
  //*p = 200;  //error                                                                                              
  //q = 200;  //error                                                                                               
  //**q = 200; //error 因为*q已经是个整型变量了,所以前面不能再加*号                                                
    * q =200;                                                                                                       
//	free(q);  //是把q所指向的内存释放掉,必须注释掉,否则会导致第17行代码会出错                                      
}                                                                                                                   
int main(void)                                                                                                      
{                                                                                                                   
        int *p = (int *)malloc(sizeof(int)); //动态分配int类型的字节数4个字节,sizeof(int)的返回值是int                   
        *p = 10;                                                                                                          
	printf("%d\n",*p);   //10                                                                                         
	f(p);    //p是int *类型                                                                                           
	printf("%d\n",*p);  //200   //第17行                                                                              
	return 0;                                                                                                         
}                                                                                                                   
	解析:                                                                                                              
		因为f(p)调用上面的f函数,而这个括号内p存放的是动态内存分配而来的第一个字节的地址,那么将这个地址传递给q,那么   
		void f(int *q)中q的值就是这个地址,跟p等同,而*q=200 是给*q这个整型变量赋值200,即改变了*q 的值,也相当于改变了
		*p的值为200,所以最终*p的输出值也为200                                                                          
					                                                                                                                
		而如果free(q);生效,则因为最终q指向的是sizeof申请来的整型的4个字节,所以如果生效,则会释放掉申请来4字节的内存。 
		从而导致出错。                                                                                                  

动态一维数组的构造:                                                                                                  
  -------------------------------                                                                                     
	#include <stdio.h>                                                                                                  
	#include <malloc.h>                                                                                                 
	int main(void)                                                                                                      
	{                                                                                                                   
		int a[5]; //如果int占4个字节的话,则本数组总共包含有20个字节,每个4个字节为一个元素,从a[0]开始,后面依次类推。   
		int len;                                                                                                          
		int * pArr;                                                                                                       
		int i;                                                                                                            
		printf("请输入你要存放的元素的个数:\n");                                                                         
		scanf("%d",&len);                                                                                                 
		pArr = (int *)malloc(4 * len);  //动态的构造了一个数组,因为是整型指针变量,一个元素占4个字节,而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);  //释放掉pArr所指向的动态数组分配的内存                                                               
		                                                                                                                  
		return 0;	                                                                                                        
	}                                                                                                                   
	                                                                                                                    
  解析:                                                                                                               
  		动态数组在使用上是跟静态数组的使用方式是一样的,只是构造的时候不一样而已。                                      
  	                                                                                                                  
  		因为pArr是整型指针变量占4个字节,所以动态内存分配后,指向的是内存分配的20个字节中的前4个字节,如果pArr+1 则表示 
  		指向的是第二个4个字节(即第5个字节到第8个字节),而不是在前面4字节的基础上+1成为5个字节。因为每4个字节为一部分。
  		由几个字节为一部分,需要由pArr的指针变量类型来决定。                                                            
  		                                                                                                                
  		pArr = (int *)malloc(4 * len);等同于int pArr[0]、int pArr[1]、int pArr[2]、int pArr[3]、int pArr[4]             
  		即int pArr[5]                                                                                                   
  		动态的构造了一个一维数组,该数组的数组名是pArr,数组长度是len,单个元素如上所示。                                
  		                                                                                                                
  		上面静态的a[5]有静态的20字节的内存                                                                              
  		下面pArr动态申请的有20个字节的内存                                                                              
  				由上可知:                                                                                                  
  						a[0]是第一个元素,占用了20个字节的前4个字节                                                             
  				那么:pArr[0]同样也是占用了动态分配的20字节的前4个字节                                                      
  							又pArr[0]等同于 *(pArr+0)                                                                             
  							所以例如:a[2]就等同于pArr[2]                                                                         
  							                                                                                                      
  		 那么如何动态的增加数组的长度呢:                                                                               
  		 可以使用realloc函数:realloc(aArr,100)  括号里面,前面表示数组名,后面表示要扩充的字节数容量上限。             
  		 如果pArr当初指向的是50个字节的内存,那么运行的时候就会扩充到100.前50个字节的数据会保留。                       
  		 如果pArr当初指向的是150个字节的内存,那么运行的时候就缩小到100,后50个字节的数据会丢失。                       

                                  

		  #include <stdio.h>                                                                                                 
		  #include <malloc.h>                                                                                                
		  void f(int *q)                                                                                                     
		  {                                                                                                                  
		  		*q = 10;                                                                                                       
		  }	                                                                                                                 
		  //void g(int **p)                                                                                                  
		  //{                                                                                                                
		  //}					                                                                                                       
		  int main(void)                                                                                                     
		  {                                                                                                                  
		  	int *p = (int *)malloc(4);  //动态请求4字节  p指向的是(int*)                                                   
		  	printf("*p = %d\n",*p);   //输出的是垃圾数字                                                                     
		  	f(p);                                                                                                            
		  //g(&p);               //p是int*,&p是int**                                                                        
		  	printf("*p = %d\n",*p);                                                                                          
		  	                                                                                                                 
		  	return 0;                                                                                                        
		  }	                                                                                                                 
		  程序运行的结果为:*p = 10                                                                                          
		  ---------------------------                                                                                        
		  #include <stdio.h>                                                                                                 
		  #include <malloc.h>                                                                                                
		  void f(int **q)                                                                                                    
		  {                                                                                                                  
		  	**q = **q + 30;                                                                                                  
		  }                                                                                                                  
		  int main(void)                                                                                                     
		  {                                                                                                                  
		  	int i;                                                                                                           
		  	int *p;                                                                                                          
		  	printf("请输入一个数字:\n");                                                                                    
		  	scanf("%d",&i);                                                                                                  
		  	p = (int *)malloc(4);  //动态请求4个字节的内存  //第13行                                                         
		  	p = &i;                                                                                                          
		  	f(&p);                                                                                                           
		  	printf("i = %d\n",i);                                                                                            
	//		free(p);  error,此处不能添加,否则会有内存报错。                                                                
		  	return 0;                                                                                                        
		  }                                                                                                                  
		  程序运行的结果为:i = 输入的任何数+30后的结果                                                                      
		  如果将第13行取消,程序依然可以运行,只是却变成了由系统自行分配的静态内存。                                         
		  --------------------------------------------------------------------------                                         
		静态内存和动态内存的区别比较:                                                                                       
				静态内存是由系统自动分配,由系统自动释放                                                                         
				静态内存是在栈中分配的                                                                                           
				                                                                                                                 
				动态内存是由程序员手动分配,手动释放,如果忘了释放,就会出现内存泄漏,内存越用越少,最后就会死机。               
				动态内存是在堆分配的  		堆就是堆排序                                                                           
				                                                                                                                 
		-----------------------------------------------                                                                      
		跨函数使用内存的问题:                                                                                               
				静态变量不能跨函数使用内存:                                                                                     
				#include <stdio.h>                                                                                               
				void f(int **q)                                                                                                  
				{                                                                                                                
					int i = 5;                                                                                                     
					//**q等价于*p   *q等价于p    q和**q都不等价于p                                                                 
					//*q = i;  error,因为*q = i; 等价于 p = i 这样写是错误的,而p中存放的是地址不是变量                           
					*q = &i;  //  p = &i                                                                                           
				}                                                                                                                
				int main(void)                                                                                                   
				{                                                                                                                
					int *p;                                                                                                        
					f(&p);    //第12行                                                                                            
					printf("%d\n",*p);  //本句语法没有问题,但逻辑上有问题。                                                       
															//不能读取不属于自己的内存,在规则上讲  //第13行                                           
					return 0;                                                                                                      
				}                                                                                                                
				程序的运行结果为:5   .                                                                                          
				解析:                                                                                                           
						此程序在语法上是没有问题的,但是在现实中逻辑上是有问题的,不能这样去写程序。                                 
						程序在运行到第12行的时候,实际上f函数的静态内存已经由系统自动释放掉了,                                      
						所以这个时候第13行的p指向的i变量就不存在了,换句话说就是无法访问了。                                         
						由此可见静态变量当被终止的时候就不能够被其他函数使用了。                                                     
				----------------------------------------------------------------------------------                               
				动态内存可以跨函数使用:                                                                                         
                                #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; error                                                                                          
                                   **q = 5; //*p = 5;                                                                                               
                                }                                                                                                                
                                int main(void)                                                                                                   
                                {                                                                                                                
                                   int *p;                                                                                                        
                                   f(&p);                                                                                                         
                                   printf("%d\n",*p);   //  第15行                                                                                
                                   return 0;                                                                                                      
                                }                                                                                                                
                               运行结果为:5                                                                                                    
                               解析:                                                                                                           
                                    因为是动态分配的内存 而p指向的是malloc(sizeof(int))中的int的4个字节的内存,而最终此程序并没有手动释放内存的  
                                    free(q),且动态内存是在堆里面进行分配的不存在出栈,所以在最后第15行,仍然可以访问之前动态分配的内存。        
        ---------------------------------------------------------------------------------------------------------------- 




                                        

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值