【C语言】一、内存管理

一、C语言中的内存分区

C语言中内存分为四个区域,分别是栈区(stack)、堆区(heap)、数据区(data)、代码区(code)

1.栈区(Stack)

存储函数调用时的局部变量、函数参数、返回值等信息。栈区由编译器自动管理,每个函数调用时,栈区会自动分配一块内存,函数返回时,该内存会被自动释放。

例如:下面的func函数中的参数ab以及内部的局部变量c,都是存在于内存中的栈区,当函数调用完成之后就会自动释放。

int func(int a, int b){
    
    
    int c;
    c = a > b ? a : b;
    return c;
}

int main() {
    
    
    func(3,2);
    return 0;
}

2.堆区(Heap)

堆区是由程序员手动分配和释放的内存区域,如果没有释放可能会由系统进行回收。例如malloccallocfree等动态内存分配都是操作堆内存。

例如:下面申请了一块内存大小为int类型数据大小的内存空间,并将指针a指向这个空间,然后向a中存入数字5,最后释放a的内存。

int main() {
    
    
    int *a = malloc(sizeof(int));
    *a = 5;
    printf("a未释放前:%d\n",*a);
    free(a);
    printf("a释放之后:%d\n",*a);
    return 0;
}

输出:

a未释放前:5
a释放之后:11338064

可以看到,内存被释放之后我们申请的内存空间的值已经变成了随机值。
注意:在手动申请内存之后一定记得手动释放,不然可能会有内存泄漏的问题

3.数据区(Data)

数据区主要用来存放全局变量、静态变量、常量,这些变量在程序运行期间一直存在,直到程序结束才被释放。

例如:下面定义的全局变量global_var和静态变量static_var以及常量const_var都是在程序运行时都是存储在数据区的。

#include <stdio.h>

int global_var = 10; // 全局变量

int main() {
    
    
  static int static_var = 20; // 静态变量
  const int const_var = 30; // 常量
  return 0;
}

4.代码区(Code)

存储程序的二进制代码,是只读的,不允许写入数据。在程序运行时,代码区的内容被复制到内存中的指令寄存器中执行。

例如:下面执行的输出"Hello World !",在编译完成后,生成的可执行文件中,printf函数的代码将被存储在代码区。

#include <stdio.h>

int main() {
    
    
  printf("Hello, world!\n");
  return 0;
}

二、内存管理的函数

1.动态内存分配函数

参考C语言基础知识:动态内存分配

2.内存操作函数

C语言提供了对内存空间进行复制、移动、修改值操作的函数

1)memcpy

内存复制函数,将源空间的值,复制固定字节给目标空间

  • 函数原型:void *memcpy(void *dst, const void *src, size_t size);
    • dst:目标空间指针(地址)
    • src:源空间指针(地址)
    • size:复制的字节数

例如:下面定义了一个字符串str1,将str1中的前7个字节复制到了str2中。

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

int main() {
    
    
    const char *str1 = "www.yhcblog.ltd"; // 定义一个字符串常量
    char str2[10]; // 定义一个空字符数组
    printf("str1:%s\tstr2:%s\n",str1,str2);
    memcpy(str2,str1,7); // 将str1的前面7个字节的值复制到str2中
    printf("str1:%s\tstr2:%s\n",str1,str2);
    return 0;
}

输出:

str1:www.yhcblog.ltd   str2:
str1:www.yhcblog.ltd   str2:www.yhc

2)memmove

memcpy功能一致,区别在于当源空间与目标空间有重叠的时候,memcpy可能会出现问题,memmove能正确处理。

  • 函数原型:void *memmove(void *dst, const void *src, size_t size);
    • dst:目标空间指针(地址)
    • src:源空间指针(地址)
    • size:复制的字节数

3)memset

修改内存地址指定字节的值

  • 函数原型:void *memset(void *dst, val, size_t size);
    • dst:要修改的空间指针(地址)
    • val:要改成的目标值(int类型的ASCII码或者字符类型)
    • size:修改的字节数(从指针位置开始往后数)

例如:下面将前面3个字符www改成a

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

int main() {
    
    
    char str[] = "www.yhcblog.ltd";
    printf("修改前:%s\n",str);
    memset(str, 'a', 3);
    printf("修改后:%s\n",str);

    return 0;
}

输出:

修改前:www.yhcblog.ltd
修改后:aaa.yhcblog.ltd

猜你喜欢

转载自blog.csdn.net/m0_56963884/article/details/129200167