【黑马程序员】c语言的动态内存分配

来源:互联网 发布:超星尔雅网络登录页面 编辑:程序博客网 时间:2024/05/16 06:03

---------- IOS培训java培训、期待与您交流! ----------


首先介绍c语言中最常使用的内存分配方式

//void *malloc(size_t size);

//泛型指针  可以赋给任何类型的指针变量 

malloc存在于堆段。而我们平时调用函数时,在在栈段。

int main(int argc,const char * argv[]) {

  

   char *p = malloc(1000);

    p[0];//开辟第一个堆空间的第一个字节

    p[1];//*(p+1)

   if (p==NULL) {

        perror("malloc error");

       exit(-1);

    }

    p[0]='A';//堆空间的首地址存上了‘A’

     

   free(p);  //堆空间释放

    return 0;

}

而如果我们在方法里这样写

int * func(){

   int a;   //a 是在栈里面的

     a=10;

    return &a;

}

这样是不可以的。因为a是一个局部变量,func方法运行完后,就收回了a所在的栈空间;

但是我们这样写

int * func(){

   int a;   //a 是在栈里面的

   int *p1=malloc(4);

   if (!p1) {

        perror("malloc p1 error");

       exit(-1);

    }

    return p1;

}

//这是可以的,因为p在堆里面。 堆空间不会随着func的消失而消失


特别注意的是:

    //栈空间   静态内存分配 编译时决定的

    //堆空间   动态内存分配  运行时决定的

    

    

//    静态内存分配 大小编译时决定   编译器分配的 自动释放   数据 只读

//    动态内存分配 大小运行时决定   程序员分配的 手动释放的   堆段

-------------------------以下是静态内存分配----------------------------------

   char buf[10001]; //不能灵活调整

   int i=0;

   while (i++<100) {

       scanf("%s",buf);

       printf("%s\n",buf);

    可以看到,当我们要往char字符中存取一些数据,这样普通的做法,就显得太浪费。比如我们第一次输入1000个,之后99次每次都输入几个字符。这样子的做法就显示不够灵活。

--------------以下为动态内存分配---------------------

int main(int argc,const char * argv[]) {

  int n;

   int i=0;

   while (i++<100) {

       scanf("%d",&n);

       char *buf = malloc(n+1);

       if (!buf) {

           perror("malloc error");

           exit(-1);

        }

       scanf("%s",buf);

       printf("%s\n",buf);

       free(buf);

    }

    

   return 0;

}

这样做的好处不言而喻。我们每次可以根据自己的需求定义空间的大小。避免空间上的浪费 。


另外C语言跟内存申请相关的函数主要有 alloca,calloc,malloc,free,realloc,sbrk等.其中alloca是向栈申请内存,因此无需释放. malloc分配的内存是位于堆中的,并且没有
初始化内存的内容,因此基本上malloc之后,调用函数memset来初始化这部分的内存空间. calloc则将初始化这部分的内存,设置为0. 而realloc则对malloc申请的内存进行大小的调整.申请的内存最终需要通过函数free来释放. sbrk则是增加数据段的大小;
malloc/calloc/free基本上都是C函数库实现的,跟OS无关.C函数库内部通过一定的结构来保存当前有多少可用内存.如果程序malloc的大小超出了库里所留存的空间,那么
将首先调用brk系统调用来增加可用空间,然后再分配空间.free时,释放的内存并不立即返回给os,而是保留在内部结构中. 可以打个比方: brk类似于批发,一次性的向OS申请大的内存,而malloc等函数则类似于零售,满足程序运行时的要求.这套机制类似于缓冲.使用这套机制的原因: 系统调用不能支持任意大小的内存分配(有的系统调用只支持固定大小以及其倍数的内存申请,这样的话,对于小内存的分配会造成浪费; 系统调用申请内存代价昂贵,涉及到用户态和核心态的转换.


函数malloc()和calloc()都可以用来分配动态内存空间,但两者稍有区别。    
    malloc()函数有一个参数,即要分配的内存空间的大小:   
    Void *malloc(size_t size);
calloc()函数有两个参数,分别为元素的数目和每个元素的大小,这两个参数的乘积就是要分配的内存空间的大小:    
    void *calloc(size_t numElementssize_t sizeOfElement);
    如果调用成功,函数malloc()和calloc()都将返回所分配的内存空间的首地址。

malloc() 函数和calloc ()函数的主要区别是前者不能初始化所分配的内存空间,而后者能。
总之,当你在calloc()函数和malloc()函数之间作选择时,我们只需考虑是否要初始化所分配的内存空间,而不用考虑函数是否能返回一个数组。
0 0
原创粉丝点击