1. 内存的五大区域.
栈: 局部变量.
堆:堆区中的字节空间允许程序员手动的申请.
BSS段:未初始化的全局变量、静态变量.
数据段:已经初始化的全局变量、静态变量和 常量数据.
代码段:存储代码的.
注意:常量数据只保存一份,保存常量数据的时候会先检测数据段是否已有要保存的常量数据,如果有则用原来的,如果没有则新开辟空间保存常量数据。
2. 如何向堆区申请字节空间来使用.
1).我们在堆中申请的字节空间.如果我们不主动释放.那么系统是不会释放到的.除非程序结束了.
2).在堆中申请字节空间的步骤.
a. 申请.
b. 使用.
c. 释放.
3).如何在堆区申请指定字节数的字节空间呢?
malloc()
calloc()
realloc()
这3个函数都是和申请字节空间有关的. 这几个函数的声明 是放在1个叫做stdlib.h的系统头文件中.
4). malloc函数.
0).作用: 向堆空间申请指定字节的空间来使用.
1). 参数只有1个:size_t类型的也就是unsigned long.
参数代表的意义: 向堆内存申请多少个连续的字节空间.
2).做的事情: 在堆内存中申请连续的参数个字节空间.
3). 返回值是: void *.
void *代表.没有类型的指针.
返回的是创建的空间中第1个字节的地址.
地址没有类型的. 只是返回了第1个字节的地址.没有说这个指针是什么类型的.
4).我们应该使用什么类型的指针变量来保存malloc函数返回的地址呢?
那就要看你想要如何去操作申请的这些字节空间.
如果你想要1个字节1个字节的操作.那么就使用char指针.
如果你想要4个字节4个字节的操作.并且当做整型来操作那么就是要int指针.
如果你想要8个字节8个字节的操作.那么就是要double指针.
如果你想要4个字节4个字节的操作.并且当做单精度浮点型来操作那么就是要float指针.
就要看你想如何操作申请的这些字节空间.
int* p1 = malloc(8);
*p1 = 100;操作的时候是以4个字节为基本单位.
char* p1 = malloc(8);
*p1 = 100;操作的时候是以1个字节为基本单位.
这样的话.我们就可以在堆内存中申请任意字节数的空间来使用.
通过指针来使用申请的空间.
5).在堆区申请的字节空间是从低地址向高地址分配.
每次申请的字节地址都是从0开始.每一次申请的字节空间不一定挨在一起.
但是. 每一次申请的指定个字节这些字节一定肯定决定是连续的.
6).在堆区申请的字节,里面是有值的.值是垃圾值.不会自动清零.
7).在向堆区申请字节空间的时候,有可能会申请失败.
如果申请失败返回的指针就是NULL值.
我们申请完空间之后,最好是判断1下.判断是否申请成功.
int* p1 = malloc(4);
if(p1)
{
//代表申请成功,要做的事情放这就可以了.
}
8).申请的空间使用完毕之后,一定要记得释放.
释放申请的堆空间:
free(指针);
如果没有free程序结束才会释放.
记住,一定要释放. 因为我们的程序有可能会运行很久.
如果非要等到结束的时候自动释放 那就晚了.
3. calloc函数.
1).作用: 向堆区申请指定字节数的空间.
2). 格式:
参数1: 多少个单位.
参数2: 每1个单位的字节数.
calloc(4,sizeof(int));
表示申请4个int空间.
3). 与malloc的优势
calloc申请的字节,申请完之后,系统会将字节中的数据清零.
4. realloc函数.
1). 作用: 扩容.
2).注意: 我们有了指针 几乎就可以操作内存上的每一个字节.
但是我们还是建议,不要乱来. 只操作我们申请的字节空间.
因为.有可能会出现一些问题.
3).当我们发现我们之前在堆区申请的字节空间不够用的时候.
就可以使用realloc函数来为我们的字节空间扩容.
a. 如果原来的空间后面还有剩余的空间.并且足够扩容.那么直接就扩容在屁股后面.
b. 如果原来的空间后面有剩余空间但是剩下的空间不够扩容.就重新找1块足够的空间申请.
将原来的数据拷贝过来. 原来的空间被自动释放.