C动态内存分配

存储划分

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

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

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

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

静态区/全局区

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

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 
#include 

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 
#include 

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 
#include 

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 
#include 

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 
#include 
#include 

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 
#include 
#include 

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 
#include 
#include 
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 
#include 
#include 
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 
#include 
#include 

int main(int argc, const char * argv[])
{
    int n = 3;
    int *arr = (int *)calloc(n, sizeof(int));
    for(int i=0; i
// 按新的长度重新分配内存,需使用free释放内存。
void * realloc(void *p, unsigned newsize);
#include 
#include 
#include 

int main(int argc, const char * argv[])
{
    int n = 3;
    int *arr = (int *)calloc(n, sizeof(int));
    for(int i=0; i

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

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

int main(int argc, const char * argv[])
{
    int n = 5;
    int *arr = (int *)calloc(n, sizeof(int));
    for(int i=0; i
// 内存比较,比较结果分大于0、小于0、等于0
int memcmp(const  void *buf1, const void *buf2, unsigned int count)
#include 
#include 
#include 

int main(int argc, const char * argv[])
{
    int size = 5;
    int *arr = (int *)calloc(size, sizeof(int));
    for(int i=0; i

你可能感兴趣的:(C动态内存分配)