🔥个人主页:北辰水墨
🔥专栏:C++学习仓
本节我们来讲解C/C++的内存区域划分,文末会附加一道题目来检验成果(有参考答案)
一、大体有哪些区域?分别存放什么变量开辟的空间?
栈区:局部变量,函数的参数
堆区:动态分配的内存
静态区:静态变量,全局变量
常量区:数字常量,字符串常量
代码区:被编译后的程序代码(二进制代码)
二、各个区域的特性:
栈区:
在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元会自动释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存空间有限。栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等。
堆区:
堆区一般存储的是动态内存,如由malloc,calloc,realloc
动态开辟的空间。这些空间一般由程序员分配释放,若不释放,程序结束时可能由OS回收,但若程序没有结束,则会造成内存泄漏,因此动态开辟的空间一定要记得free释放。内存分配的方式类似于链表。
静态区:
(static)存放全局变量、静态数据。程序结束后(不是函数结束)由系统释放。
常量区:
存放数字常量,字符串常量。
代码区:
被编译后的程序代码(二进制代码)。
三、如何区分变量开辟的空间是那个区域?
在它定义的时候:
1.是局部变量还是全局变量。
2.有没有static关键字。
3.有没有malloc函数在堆区空间开辟空间。
4.是不是常量。
四、区分变量和变量名:
上面提到的变量(下面的题目我也是直接叫变量了):开辟的空间存在哪个区域
变量名:存储在编译器的内存中,而不是程序运行时的五大区域中。
编译器会根据程序中定义的变量、函数和其他标识符的信息构建符号表,并将其保存在内存
中以便后续的编译和链接操作使用。
符号表:在编译连接时,会通过这个符号表将相应的变量名,函数名都映射成对应的地址
五、请听题!
int globalvar = 1;
int staticGlobalVar = 1;
int main()
{
static int staticVar = 1;
int localVar = 1;
int num1[10] = { 1,2,3,4 };
char char2[] = "abcd";
const char* pChar3 = "abcd";
int* ptr1 = (int*)malloc(sizeof(int) * 4);
int* ptr2 = (int*)calloc(4, sizeof(int));
int* ptr3 = (int*)realloc(ptr2, sizeof(int));
free(ptr1);
free(ptr2);
free(ptr3);
return 0;
}
(1)选择题:
下面的变量在内存的哪个区域?
选项:A、栈区 B、堆区 C、静态区 D、常量区
① globalvar___ staticGloalVar___ staticVar___
② localVar___ num1___
③ char2___ *char2___
④ pChar3___ *pChar3___
⑤ ptr1___ *ptr1___
(2)答案:① C C C
② A A
③ A A
④ A D
⑤ A B
(3)解析:
①静态变量和全局变量 存放在 静态区
②局部变量 存放在 栈区。num1也是一个局部的变量(在栈区开辟了一块数组)
③char2是一个局部变量
*char2解引用表示它指向的那一块数组的首元素,而数组的首元素存储在栈区中,这里你们一定有疑惑,为什么字符串存储在栈区。其实不然,这里表示的char类型的数组会在栈区开辟5个字节的空间,然后把在常量区的字符串“abcd\0”拷贝到数组中。
所以*char指向的数组是在栈区。
④pChar3也是一个局部变量,在栈区。
*pChar3指向的是常量区的字符串“abcd\0”,所以*pChar3表示字符串的首元素a,a是存放在常量 区的。
⑤ptr1也是一个局部变量,存放在栈区。它指向的是一块堆区的内存块。
*ptr1,是对ptr1指针解引用,就是堆区的那一块空间。
这么说你们肯定还是发蒙,那我画个图来带你们理解!、