C 语言动态内存分配

C语言中内存管理主要分为以下几块:

  • 栈区
  • 堆区
  • 全局区或静态区
  • 字符常量区
  • 程序代码区

一般栈区都是由系统自动分配回收,但是栈区大小是有限制的,windows下一般为程序分配的栈内存为2M左右。超出就会抛出stack overflow错误.

如下:

void main(){
    //40M
    //静态内存分配
    int a[1024 * 1024 * 10];
    getchar();
}

上面的代码运行时就会抛出 stack overflow。这种情况下,就需要程序人员,手动在堆区分配与释放内存。

在C语言中内存管理主要通过以下几个函数进行:

  • malloc()
  • realloc()
  • calloc()
  • free()

malloc与calloc函数都是进行堆内存分配,区别主要在于传参形式不一样:

    //8M
    int * p = malloc(1024 * 1024 * 2 * sizeof(int));
    //8M
    int * p2 = calloc(1024 * 1024 * 2,sizeof(int));

realloc函数用于重新分配内存。分为两种情况:

  • 缩小:缩小的那一部分数据会丢失。
  • 增大:
    • 如果当前内存段后面有需要的内存空间,直接扩展这段内存空间,realloc返回原指针
    • 如果当前内存段后面的空闲字节不够,那么就使用堆中的第一个能够满足这一要求的内存块,将目前的数据复制到新的位置,并将原来的数据库释放掉,返回新的内存地址
    • 如果申请失败,返回NULL,原来的指针仍然有效

示例:

void main(){
    int len;
    printf("第一次输入数组的长度:");
    scanf("%d", &len);

    //int* p = malloc(len * sizeof(int));   
    int* p = calloc(len, sizeof(int));
    int i = 0;
    for (; i < len; i++){
        p[i] = rand() % 100;
        printf("%d,%#x\n", p[i], &p[i]);
    }

    int addLen;
    printf("输入数组增加的长度:");
    scanf("%d", &addLen);
    //内存不够用,扩大刚刚分配的内存空间
    //1.原来内存的指针 2.内存扩大之后的总大小        
    int* p2 = realloc(p, sizeof(int)* (len + addLen));
    if (p2 == NULL){
        printf("重新分配失败");
        free(p);
        p = NULL;
        return;
    }
    
    //重新赋值
    i = 0;
    printf("--------------------------\n");
    for (; i < len + addLen; i++){
        p2[i] = rand() % 200;
        printf("%d,%#x\n", p2[i], &p2[i]);
    }

    //手动释放内存
    if (p2 != NULL){
        free(p2);
        p2 = NULL;
    }

    getchar();
}

free函数用于释放内存。如上所示。

Note:同一块内存区不能多次释放,释放完之后(指针仍然有值),一般地给指针置NULL,标志释放完成,避免这种情况。重新分配内存成功后,如果是原地址,上面即是p =p2.如果是新开辟的内存,则p会被系统自动释放,所以后面只释放p2即可。

下面再看一个内存分配的例子:


void main(){

    int len = 4;
    char ** args = malloc(sizeof(char*)*len);
    int i = 0;
    for ( ; i < 4; i++)
    {
        args[i] = malloc(sizeof(char)* 20);
        sprintf(args[i],"array[%d]",i);
    }

    for ( i = 0; i < 4; i++)
    {
        free(args[i]);
    }

    free(args);

    getchar();
}

上面的示例中,我们进行了两次开辟,好像跟上面讲的不一样,数组开辟空间后,为啥单个元素还要再次开辟,而上面的数组却没有?其实不然。

这里我们定义的是一个字符串数组。但是C中是没有字符串的,每一个字符串其实是一个字符数组,所以,它相当于是一个二维数组,所以需要再次分配内存。

我们再举个二维数组,动态分配的例子:

#include <stdio.h> 
#include <stdlib.h> 
int main() 
{ 
int n1,n2; 
int **array,i,j; 
printf("请输入所要创建的动态数组的第一维长度:");
scanf("%d",&n1);
printf("请输入所要创建的动态数组的第二维长度:");
scanf("%d",&n2); 
array=(int**)malloc(n1*sizeof(int*)); //第一维 
for(i=0;i<n1; i++) 
{ 
array[i]=(int*)malloc(n2* sizeof(int));//第二维 
}
for(i=0;i<n1;i++)
{
for(j=0;j<n2;j++) 
{ 
array[i][j]=i*n2+j+1; 
printf("%d\t",array[i][j]); 
} 
printf("\n");
}
for(i=0;i<n1;i++) 
{ 
free(array[i]);//释放第二维指针 
} 
free(array);//释放第一维指针 
return 0; 
}

这两个例子,对比着看,相信就不会有啥疑惑了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容

  • C语言中内存分配 在任何程序设计环境及语言中,内存管理都十分重要。在目前的计算机系统或嵌入式系统中,内存资源仍然是...
    一生信仰阅读 1,142评论 0 2
  • Android NDK开发之旅 目录 C 内存管理函数 C 语言为内存的分配和管理提供了几个函数。这些函数可以在 ...
    香沙小熊阅读 1,758评论 1 0
  • 为什么使用动态内存分配 当你声明数组时,你必须使用一个编译时常量来指定数组的长度。但是,数组的长度常常在运行时才能...
    d9fc24a0c9a9阅读 2,321评论 0 0
  • 逻辑上的分区 栈区 堆区 静态区 常量区 代码区 代码区,常量区,静态区,堆区,栈区这个排列顺序按照地址由小到大排...
    MathCat阅读 614评论 1 0
  • 想要好的业绩就必须要有高的单笔,高单笔、高裤销、高总销,所以要重视单笔,单笔分享02店:每天意识要强,进店顾客拒绝...
    positive默然阅读 68评论 0 0