12-C语言内存管理

内存空间

进程空间图示

image

栈内存(Stack)

  • 栈中可以存放任意类型的变量, 即自动类型的局部变量, 随用随开,用完即消.
  • 栈内存分配从地址大的开始分配
  • 栈的内存大小有限, 所以特别在使用递归的时候一定要注意, 栈的溢出问题;
#include 

int main()
{
    // 存储在栈中, 内存地址从大到小
    int a = 10;
    int b = 20;
    printf("&a = %p\n", &a); // &a = 0060FEAC
    printf("&b = %p\n", &b); // &b = 0060FEA8

    return 0;
}

堆内存(Heap)

  • 堆内存可以存放任意类型的数据, 但需要自己申请与释放
  • 堆大小, 想象中的无穷大, 但实际使用中, 受限于实际内存的大小和内存是否连续性;
#include 
#include 

int main()
{
    // 存储在栈中, 内存地址从小到大
    int *p1 = malloc(4);
    *p1 = 10;
    int *p2 = malloc(4);
    *p2 = 20;
   
    printf("p1 = %p\n", p1); //  p1 = 00762F48
    printf("p2 = %p\n", p2); // p2 = 00762F58

    return 0;
}


malloc函数

  • 格式: void * malloc(size_t _Size);

  • malloc函数作用: 用于申请堆中的内存的

  • malloc函数开辟好的存储空间,不会进行初始化

  • free函数: 释放我们在堆内存中开辟的一块内存空间

  • memset 函数: 给指定的堆内存进行初始化

  • 申请4个字节的存储空间

    • (int *)强制类型转换
    • malloc函数返回的是void * ,而我们开辟的是4个字节,正好是int类型,
    • 所以最好将void *转换为int *,因为只有指针类型是int 类型
    • 将来操作这块内存的时候,我们才知道应该操作多少个字节
    int *p = (int *)malloc(sizeof(int));
    printf("*p = %i\n", *p);
    
  • 小例子

#include 

int main()
{
    // 强制类型转换
    int *p1 = (int *)malloc(4);
    int *p2 = (int *)malloc(sizeof(int));
    *p1 = 123;
    *p2 = 456;
    printf("*p1 = %i\n", *p1);
    printf("*p2 = %i\n", *p2);

    printf("p1 = %i\n", p1);   // 10162952  观察可知,从低地址开始存放
    printf("p2 = %i\n", p2);   // 10162968
    
    // 通过free函数来手动释放我们申请的空间
    free(p1);
    free(p2);
    // free函数,我们只传递了内存的地址,系统如何知道应该释放多少个字节的存储空间
    // 在利用,malloc分配的时候,系统就保存了该指针对应的内存大小;
    return 0;
}


  • 注意点:

    • 使用malloc函数必须导入一个头文件 stdlib.h
    • 通过malloc申请的空间默认存储的是垃圾数据, 也就是系统不会帮我们初始化
    • 所以一般情况下, malloc都会和memset函数结合起来使用
  • memset作用:

    • 格式: memset(void *_Dst, int _Val, size_t _Size)
    • 专门用于初始化一块内存空间
    • 第一个参数: 传入需要初始化内存的地址
    • 第二个参数: 传入需要初始化的值
    • 第三个参数: 传入需要初始化的长度
  • memset注意: 使用时必须导入一个头文件string.h

#include 

int main()
{
    int *p = (int *)malloc(3 * sizeof(int));
    printf("p[0] = %i\n", p[0]);  // 垃圾数据
    printf("p[1] = %i\n", p[1]); // 垃圾数据
    printf("p[2] = %i\n", p[2]); // 垃圾数据

    memset(p, 0 , 3*sizeof(int));
    for(int i = 0; i < 3; i++){
        printf("p[%i] = %i\n", i, p[i]); // 0 0 0
    }
    return 0;
}

calloc函数

  • calloc函数 就是对malloc的封装
  • 格式: void *calloc(size_t nmemb, size_t size);
    • 第一个参数: size_t nmemb 所需内存单元数量
    • 第二个参数: size_t size 内存单元字节数量
    • 返回值: void * 成功返回非空指针指向申请的空间 ,失败返回 NULL
int *p = (int *)calloc(3, sizeof(int));
// 告诉操作系统,需要开辟3块存储空间, 每块存储空间占用4个字节

realloc函数

  • 例如, 我们利用malloc分配4个字节, 如果4个字节不够用,则想进行扩容,这时候可以使用realloc,反之,缩小也可以

  • 注意点:

    • 利用malloc函数分配存储空间,必须是连续的,也就是在堆内存中分配内存空间必须是连续的
    • 如果利用realloc函数扩容的时候,后面没有连续的内存, 那么系统会分配一块新的内存;

你可能感兴趣的:(12-C语言内存管理)