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;
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

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