前言: 程序的执行是放入内存中的,而我们在写代码时定义的变量, 函数等是存储在内存的不同区域. 不同的区域有着不同的特性.
参考资料和网上所说的内存分区大致可以分为两种: 分四个区和分五个区.
1.四区: 栈区, 堆区, 全局(静态)区, 常量(代码)区.
2.五区: 栈区, 堆区, 全局(静态)区, 常量区. 代码区.
其实这两者就是将最后一个区分为常量区和代码区.我们介绍的话就以五区来介绍吧. 主要将最后的那个区分开理解就好. 当然还有一种分四区: 栈区, 堆区, 数据区, 代码区. 将数据区细分为全局(静态)区, 常量区.虽然这样分很好理解,但是并不那么贴切(个人感觉). 来张图片理解一下(随便百度的): 最上面的计算机内核使用的归操作系统,虽然和我们编写程序没什么关系,但是也要了解以下.
内存五区:
1.栈区:
栈区,是我们最常用到的区域, 因为我们所有的普通局部变量全部存储在这个区.就如我们定义和使用局部变量一样. 在栈区的数据是不需要我们手动去申请和释放内存的. 这个过程全部由编译器帮我们完成,所以我们的局部变量可以直接使用.
int func(int x, int y){ //传递过来的参数 在栈区
int z = x + y; //函数内部定义的局部变量在栈区
return z;
}
int main(){
int a = 3; //函数内部定义的局部变量在栈区
a += 2;
return 0;
}
2.堆区:
堆区,凡是手动malloc realloc calloc, 或者 C++中的new出来的变量都是存储在堆区. 如果学过数据结构或者用过C++的话就会知道, 数据结构中的链表是任意长度的,我们用c实现的话每个节点都是通过malloc函数创建出来的.而C++的话我们new出来的对象都是局部对象, 这些都是我们自己手动申请创建的内存.
注意: 我们手动申请的在堆区的时候,如果我们不手动释放(free)掉这段内存, 这段内存会一直占用直到程序结束. 手动释放掉内存后切记将该指针置空.
当然C++通过new 出来的对象系统会自动调用析构函数释放内存.
int *func(int x, int y){ //x y, 是在栈区
int *p = malloc(4); //p所指向的内存就存放在堆区.
*p = x+y;
return p;
}
int main(){
int *p = NULL;
p = func(3, 5);
printf("%d\n", *p);
free(p); //使用完后释放内存, 并将p置空
p = NULL;
//后续代码操作
return 0;
}
3.全局(静态)区:
全局(静态)区:故名思义,全局变量和静态变量(static)存放的在这个区.这个区域也叫可读写区, 分为.data和.bss两部分, 1 .data段(初始化全局|静态变量), 所有初始化了的全部变量存放的区域.则为数据分配空间,数据保存在目标文件中。 2 .bss段(未初始化全局|静态变量), 所有未初化的全部变量存放的区域.不给该段的数据分配空间,只是记录数据所需空间的大小。 注意: 如果我们定义了一个全部整型变量并赋予了初始值0, 如果我们不给其赋值编译器也会在使用时赋予初始值0, 为了优化会将其放入.bss段, 当作未初始化处理.(看到有人的帖子这样说的,但是我不会验证 TAT!) 附上帖子地址: http://blog.csdn.net/u010154760/article/details/46552303
int a; //全局(静态)区
//int a = 0; //据说都是在.bss段
int b = 2; //全局(静态)区, .data段
void static fun_sta(){ //这个函数是存放在代码区的.
}
void func(){
static int a = 0; //全局(静态)区. 额,这个应该也是在.bss吧.不知道有没有好心人告知一波...
static int b = 1; //全局(静态)区. .data段
}
int main(){
static int a = 3; //全局(静态)区 .data段
return 0;
}
4.常量区:
常量区: (也叫文字常量区)我们在程序中使用的一些整型常量, 浮点型常量, 还有一个很容易误会的字符串常量都是存放在常量区. 举个简单的例子: int a = 4; 我们知道a是存放在栈区的, &a的地址就是栈区的地址, 但是4却是存放在常量区.画图帮助理解.
普通的常量很好理解, 但是字符串有点特殊.举个例子.
int main(){
char *s = "abc"; //字符串
char *s1 = "abc"; //字符串
char s2[] = "abc"; //字符串数组
printf("%p\n", s);
printf("%p\n", s1);
printf("%p\n", s2);
return 0;
}
输出结果:
panyiwen@god:~/temp$ ./a.out
0x4006b4
0x4006b4
0x7ffe50893e90
可以看出指针s 和 s1指向的是同一个地址, 而s2和前两个都不同. 原因就是: s 和 s1 都是指向常量区的地址, 常量区只有一个字符串”abc”, 而s2是一个普通的局部变量数组, 那么s2就是存储在栈区的一个字符串 画图理解:
5 代码区:
代码区: 故名思义, 所有的代码是存放在这里.而且是编译后的二进制代码.当然这个区是由操作系统直接控制.
代码区和常量区因为都是不可修改的, 所以这两个区也被合并在一块称之为只读区.
再放入一张横向图片供参考.
鸣谢:
http://blog.csdn.net/czg13548930186/article/details/52766606
http://blog.csdn.net/androidxiaogang/article/details/50383516
http://blog.csdn.net/u010672206/article/details/46946593
希望能让你能有所收获, 不对的地方还请多多指教.