内容概要
一、动态内存管理
二、c语言内存布局
三、思考题
1、动态内存管理
c语言中的变量是要事先定义好才能使用,在程序执行过程中动态创建是不允许的。但是在C99后已经实现了变量动态创建
如果想要动态创建变量,可以使用库stdlib.h下提供的功能
-malloc(参数一)
参数一:要开辟多少字节的内存
功能:创建一个动态的内存,这个内存位于堆中
返回值:返回一个指向这个内存位置的void类型指针
#include <stdio.h> #include <stdlib.h> int main(void){ int *pa; pa = (int *)malloc(sizeof(int)); //创建一个int类型大小的内存空间 *pa = 120; printf("%d %p\n", *pa, pa); free(pa); //释放pa指向的内存,这个内存应该有malloc,calloc或者realloc开辟的内存(存放在堆中) return 0; }
需要注意的是malloc开辟的空间存放在堆区,这部分内存不会在函数调用结束之后释放,需要程序员指定才会释放
像是在python使用open()函数之后使用close()向操作系统发出回收文件资源的命令
#include <stdio.h> #include <stdlib.h> int main(){ int *pa; while (1){ pa = (int *)malloc(sizeof(int)); } return 0; }
把内存搞炸
#include <stdio.h> #include <stdlib.h> int main(){ int *pa; while (1){ pa = (int *)malloc(sizeof(int)); free(pa); } return 0; }
炸不了了
使用malloc也可能调用失败,只是函数会返回NULL指针
像操作数组那样操作返回的指针
#include <stdio.h> #include <stdlib.h> int main(){ int n; int *pa; // 动态创建 printf("please input how long you want:"); scanf("%d",&n); pa = (int *)malloc(n * sizeof(int)); // 像数组一样遍历,发现是随机值 for (int i = 0; i < n; i++){ printf("%d\n",pa[i]); } // 回收资源 free(pa); return 0; }
为"数组"初始化,利用memset函数
要使用memset函数,需要导入库string.h
-memset(参数一,参数二,参数三)
参数一:动态内存指针
参数二:初始化值
参数三:动态内存大小
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(){ int *pa; pa = (int *)malloc(8,sizeof(int)); // 初始化 memset(pa, 0 ,8 * sizeof(int)); for (int i = 0; i < 8; i++){ printf("%d\n",pa[i]); } return 0; }
切记要使用指针关联动态开辟的内存
#include <stdio.h> #include <stdlib.h> int main(){ int *pa; int num = 10; pa = (int *)malloc(sizeof(int)); pa = # // 再也找不到指向那个位置的内存地址了 return 0; }
同时不要对局部变量使用free
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(){ int *pa; int num = 10; pa = (int *)calloc(8,sizeof(int)); pa = # free(pa) } return 0; }
-calloc(参数一,参数二)
参数一:存放元素的个数
参数二:每个元素的长度
功能:在上面的例子中,会发现遍历未初始化的动态内存,会打印随机的数值。使用calloc函数可以在动态创建内存空间时设置初始值。
返回值:void类型指针
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(){ int *pa; pa = (int *)calloc(8,sizeof(int));for (int i = 0; i < 8; i++){ printf("%d\n",pa[i]); } return 0; }
-memcpy拷贝内存空间
-memove拷贝内存空间
-memcmp比较内存空间
-memchr在内存空间中查找一个字符
-realloc(参数一,参数二)
参数一:要更新的动态内存地址
参数二:新的内存大小
功能:更新动态内存的大小
返回值:void类型的内存地址(这个void地址可能和传入的参数相同,也可能不同)
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(){ int *pa; pa = (int *)calloc(8,sizeof(int)); printf("before: %p\n",pa); pa = (int *)realloc(pa,16 * sizeof(int)); printf("after: %p\n",pa); //两次地址应该一样 free(pa); return 0; }
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(){ int *pa; pa = (int *)calloc(8,sizeof(int)); printf("before: %p\n",pa); pa = (int *)realloc(pa,1000 * sizeof(int)); printf("after: %p\n",pa); //两次地址应该不一样 free(pa); return 0; }
如果向realloc函数传入NULL指针,就相当于调用malloc函数
一个根据用户输入创建动态"整形数组"的小练习
#include <stdio.h> #include <stdlib.h> int main(){ int num; int count = 0; int *pnum = NULL; while (1){ printf("please input a number(input -1 end process):"); scanf("%d",num); if (num == -1){ for (int i = 0; i<count; i++){ printf("%d\n",pnum[i]); } break; } count++; pnum = (int *)realloc(pnum,count * sizeof(int)); pnum[count] = num; } }
2、c语言内存管理
c语言不同类型变量内存地址的比较
#include <stdio.h> #include <stdlib.h> int global_var_a; int global_var_b = 1024; void func(void); void func(void){ ; } int main(void){ int local_var1; int local_var2 = 111; static int static_var1; static int static_var2 = 512; char *str1 = "You are right!"; char *str2 = "hello world"; int *pa = (int *)malloc(sizeof(int)); printf("addr of func is: %p\n", func); printf("addr of global_var_a is: %p\n", &global_var_a); printf("addr of global_var_b is: %p\n", &global_var_b); printf("addr of local_var1 is: %p\n", &local_var1); printf("addr of local_var2 is: %p\n", &local_var2); printf("addr of static_var1 is: %p\n", &static_var1); printf("addr of static_var2 is: %p\n", &static_var2); printf("addr of str1 is: %p\n", str1); printf("addr of str2 is: %p\n", str2); printf("addr of pa is: %p\n", pa); return 0; }
内存分段图解
使用size命令查看每个分段大小
原文:https://www.cnblogs.com/laijianwei/p/14552996.html