C动态内存分配

存储划分

在C语言中,存储区大致分为5类

  • 全局区(静态区)
  • 常量区
  • 代码区

  • 由编译器自动分配和释放
  • 在函数体中定义的变量通常在栈上
  • 栈中的变量先进后出
  • 栈中的变量一般出了函数会被释放

  • 一般由程序员分配和释放,程序员不释放,程序结束时由操作系统释放。
  • 使用malloccallocrealloc等分配内存的函数分配得到的就在堆上。
  • 释放堆内存free()

静态区/全局区

  • 全局变量和静态变量的存储是放在一块的
  • 初始化的全局变量和静态变量在一块区域
  • 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域
  • 程序结束操作系统统一释放
#include <stdio.h>

int *func()
{
    int i = 1;
    int *p = &i;
    return p;
}

int main(int argc, const char *argv[])
{
    int *fn = func();
    printf("%d\n", *fn);// 1
    printf("%d\n", *fn);// 868186003
    printf("%d\n", *fn);// 868186003

    return 0;
}
#include <stdio.h>
#include <stdlib.h>

int *func()
{
    static int i = 1;
    int *p = &i;

    //int i = 1;
    //int *p = malloc(sizeof(4));
    //p = &i;
    
    return p;
}

int main(int argc, const char *argv[])
{
    int *fn = func();
    printf("%d\n", *fn);
    printf("%d\n", *fn);

    return 0;
}
#include <stdio.h>
#include <stdlib.h>

int g = 100;//全局变量存储在全局区,程序结束后被释放。

int *func()
{
    static int i = 1;//静态变量存储在静态区,程序结束后被释放。
    int *p = &i;

    //int i = 1;
    //int *p = malloc(sizeof(int));
    //p = &i;
    
    return p;
}
int main(int argc, const char *argv[])
{
    int *fn = func();
    printf("%d\n", *fn);
    printf("%d\n", g);

    return 0;
}
#include <stdio.h>
#include <string.h>

int main(int argc, const char *argv[])
{
    char *str = malloc(sizeof(char)*10);// 堆内存
    strcpy(str, "hello");
    printf("%s\n", str);
    free(str);//释放堆内存

    return 0;
}
#include <stdio.h>
#include <string.h>

char *func()
{
    char *str = malloc(sizeof(char)*10);
    strcpy(str, "hello");
    free(str);

    return str;
}

int main(int argc, const char *argv[])
{
    char *str = func();
    printf("%s\n", str);

    return 0;
}

常量区

  • 专门存放常量的地方,例如1,3.14,'a','hello'...
  • 程序结束后系统自动释放

程序代码区

  • 存放二进制代码的区域
  • 函数通常会被编译成二进制代码,存储在代码区。
  • 函数被调用的时候,会从代码区取出,函数需要的参数以及函数体中的变量,会在栈里临时分配,函数结束时,变量会被释放。

动态内存分配

malloc

malloc()函数向系统申请分配size个连续的内存空间,返回值为void*void*属于指针类型,不代表确切的指针类型,程序员根据需要转换成自己需要的类型。

void *malloc(unsigned int size)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char * argv[])
{
    char *str = (char *)malloc(sizeof(char)*8);
    strcpy(str, "hello");
    printf("%s\n", str);//hello
    free(str);//释放堆内存
    str = NULL;//指向空指针

    return 0;
}

数组分配空间

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char * argv[])
{
    // 分配包含10个int元素的数组,本质上是分配了40个字节空间。
    int *arr = (int *)malloc(sizeof(int)*10);
    for(int i=0; i<10; i++){
        arr[i] = i+1;
    }
    for(int i=0; i<10; i++){
        printf("arr[%d] = %d\n", i,arr[i]);
    }
    free(arr);
    arr = NULL;

    // 分配2行3列的二维整型数组
    int (*p)[3] = (int (*)[3])malloc(sizeof(int)*2*3);
    for(int i=0; i<2; i++){
        for(int j=0; j<3; j++){
            p[i][j] = i+j;
        }
    }
    for(int i=0; i<2; i++){
        for(int j=0; j<3; j++){
            printf("p[%d][%d] = %d\n", i, j, p[i][j]);
        }
    }
    free(p);
    p = NULL;

    // 分配2行255列的二维字符串数组
    char (*c)[255] = (char (*)[255])malloc(sizeof(char)*5*255);
    free(c);
    c = NULL;

    return 0;
}

结构体指针

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student{
    char *name;
    int age;
} Student;

int main(int argc, const char * argv[])
{
    Student *p = (Student *)malloc(sizeof(Student));
    p->name = (char *)malloc(sizeof(char)*10);
    strcpy(p->name, "alice");
    printf("%s\n", p->name);

    free(p->name);
    p->name = NULL;
    free(p);
    p = NULL;

    return 0;
}

结构体数组

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student{
    char *name;
    int age;
} Student;

int main(int argc, const char * argv[])
{
    Student *p = (Student *)malloc(sizeof(Student)*3);
    
    return 0;
}

其他内存分配函数

// 分配n个size大小的空间,需使用free释放内存。
// 与malloc不同的是calloc申请的内存空间会初始化成0
void * calloc(unsigned n, unsigned size)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char * argv[])
{
    int n = 3;
    int *arr = (int *)calloc(n, sizeof(int));
    for(int i=0; i<n; i++){
        printf("arr[%d] = %d\n", i, arr[i]);
    }
    free(arr);
    arr = NULL;
    
    return 0;
}
// 按新的长度重新分配内存,需使用free释放内存。
void * realloc(void *p, unsigned newsize);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char * argv[])
{
    int n = 3;
    int *arr = (int *)calloc(n, sizeof(int));
    for(int i=0; i<n; i++){
        printf("arr[%d] = %d\n", i, arr[i]);
    }
    printf("-------------------------\n");

    int size = 5;
    arr = (int *)realloc(arr, sizeof(int)*size);
    for(int i=0; i<size; i++){
        printf("arr[%d] = %d\n", i, arr[i]);
    }

    free(arr);
    arr = NULL;

    return 0;
}

内存操作函数
内存操作函数即可用于堆内存也可以用于栈内存中

// str开始长度为n的所有字节赋值为c
// 用于清除结构体或数组数据
void *memset(void *str, int c, size_t n)
// 从src拷贝n个字节到dst中
void *memcpy(void *dst, const void *src)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char * argv[])
{
    int n = 5;
    int *arr = (int *)calloc(n, sizeof(int));
    for(int i=0; i<n; i++){
        printf("arr[%d] = %d\n", i, arr[i]);
    }
    printf("-------------------------\n");

    int size = 10;
    arr = (int *)realloc(arr, sizeof(int)*size);
    for(int i=0; i<size; i++){
        printf("arr[%d] = %d\n", i, arr[i]);
    }
    printf("-------------------------\n");

    // 按字节赋值
    // memset(arr, 1, sizeof(int)*size);//00000001 00000001 00000001 00000001
    // for(int i=0; i<size; i++){
    //  printf("arr[%d] = %d\n", i, arr[i]);
    // }
    // printf("-------------------------\n");

    int a[size] = {1,1,1,1,1,1,1,1,1,1};
    memcpy(arr, a, sizeof(int)*size);
    for(int i=0; i<size; i++){
        printf("arr[%d] = %d\n", i, arr[i]);
    }

    free(arr);
    arr = NULL;

    return 0;
}
// 内存比较,比较结果分大于0、小于0、等于0
int memcmp(const  void *buf1, const void *buf2, unsigned int count)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char * argv[])
{
    int size = 5;
    int *arr = (int *)calloc(size, sizeof(int));
    for(int i=0; i<size; i++){
        printf("arr[%d] = %d\n", i, arr[i]);
    }
    printf("-------------------------\n");

    int a[size] = {1,1,1,1,1,1,1,1,1,1};
    int result = memcmp(arr, a, sizeof(int));
    printf("result is %d\n", result);

    free(arr);
    arr = NULL;

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

推荐阅读更多精彩内容

  • C语言中内存分配 在任何程序设计环境及语言中,内存管理都十分重要。在目前的计算机系统或嵌入式系统中,内存资源仍然是...
    一生信仰阅读 1,148评论 0 2
  • (JG-2014-08-20)(前半部分经过网上多篇文章对比整理)(后半部分根据ExceptionalCpp、C+...
    JasonGao阅读 5,597评论 2 23
  • 1. malloc()函数 1.1 malloc的全称是memory allocation,中文叫动态内存分配。 ...
    Pitfalls阅读 1,988评论 0 5
  • 我和她从不相识,若说有什么联系的话,那边是你,唯一的联系,我爱你,你爱过她,你说你爱我 你知道吗?当HZQ离开之后...
    之青阅读 272评论 0 0
  • inode 是 UNIX 操作系统中的一种数据结构,其本质是结构体,它包含了与文件系统中各个文件相关的一些重要信息...
    StarShift阅读 285评论 0 0