唐诗开篇,与文无关(Tips:本篇不是唐诗)
观沧海
-- 曹操 朝代:东汉末年/三国(184年-220年)
东临碣石,以观沧海。
水何澹澹,山岛竦峙。
树木丛生,百草丰茂。
秋风萧瑟,洪波涌起。
日月之行,若出其中;
星汉灿烂,若初其里。
幸甚至哉,歌以咏志。
1. 如何学会阅读C语言API文档 ?
2. 静态/动态开辟内存
3. 动态开辟内存的使用场景
4. 动态开辟内存之 realloc
Tips:C语言非0即true,只要是非0就是true,0是false, 这点要和Java区分开来。
1 阅读C语言API文档?
建议
1)尽量不要copy文档中的代码,要手动敲一遍。
2)遇到传入&t &p 的时候,可以试着传入NULL试试, 就是在不去确定的情况传入 NULL的地址试试。
2 静态/动态开辟内存
2.1 静态开辟内存
栈区: 占用内存大小 最大值 2M ,大小跟平台有关系,大概是2M左右。
堆区: 占用内存大小 最大值 内存(Windows系统分配个编译器的空间)的80%左右,基本上不涉及到内存溢出问题。
栈中函数进栈出栈会自动释放内存
// int 4 个字节
int arr[10 * 1024 * 1024]; // 10M * 4 = 40M 开辟40M空间,直接崩溃 栈溢出
定义类似 int arr[9]; , int i; 之类的都属于静态开辟内存范畴
2.2 动态开辟内存
malloc等 在对队中堆中开辟的空间 , 都属于动态范畴
int * arr = malloc(1 * 1024 * 1024); // 在堆区动态开辟1M内存空间 注:* arr是个指针,不是数组
堆中进栈出栈不会自动释放内存,作为C程序员的话,堆空间开辟的内存必须释放。
free(arr); //释放内存,这里虽然释放,但是内存地址还指向堆区的位置
arr = NULL // arr重新指向一块地址 0X00000,不指向NULL可能造成悬空指针
// 悬空指针 指向的地址已经清空了
int * p; // 野指针:没有指向任何地址
3 动态开辟的使用场景
//由于 静态开辟的内存空间大小是不能修改的
int arr[6];
需要变化的空间的话,就需要动态开辟。
int num;
printf("输入需要的个数: ");
scanf("%d", &num); // 获取用户输入的函数
int * arr = (int *) malloc(sizeof(int) * num);// 动态开辟用户输入的值对应的空间大小 【堆区】
4 动态开辟之realloc
解决malloc动态开辟空间不足的情况,可以重新申请扩大内存。 (场景:用户第一次申请的内存不满足使用要求了,用realloc可以重新申请内存)
// 原来的大小 + 新增的大小 = 总大小
int num2;
printf("输入需要新增加的大小: ");
sacnf("%d", &num2); // 再一次输入需要新增加的内存大小
// void * realloc(void *上一次开辟的内存地址, 需要的总空间大小)
int * arr2 = (int *) realloc(arr, sizeof(int) * (num + num2));
if(arr2) { // 新的开辟了,可以进行操作了
}
// arr2操作完了释放空间
if(arr2) {
free(arr2);// 假如不赋值给NULL的话就会造成悬空指针
arr2 = NULL;
arr = NULL; // 防止出现悬空指针
} else {
free(arr);
arr = NULL;
}
/* realloc是在原有地址后面接上,所以大部分情况下arr 和 arr2 的首地址是一样的,
但是如果原arr空间后面没连续可用的空间了,realloc时系统就会把原来的arr复制到新开辟的地址位置,
再衔接上需要新增的空间大小,此时arr和arr2地首地址就不一样了。
*/
Tips:
野指针: 定义的时候没初始化,不知道指向哪里。
悬空指针:是其指向的地址被释放掉了,但是没将其设置为NULL。