7.【动态内存分配】

来源:互联网 发布:看视频软件有卡顿 编辑:程序博客网 时间:2024/06/05 08:47
【专题】【重点】                                                                        
动态内存分配【重点 难点】                                                             
传统数组的缺点:                                                                     
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行,仍然可以访问之前动态分配的内存。                ---------------------------------------------------------------------------------------------------------------- 




                                        

0 0
原创粉丝点击