C++经典的内存模型分区划分为代码区,数据区,堆区,栈区;
也有更细一些的说法:命令行,代码区,全局静态区,BBS段,常量区,堆区,栈区。
下面我在windows下,编译器为codeblocks写了下列代码来认识一下。
为了保证显示数据存放的连续性,同种数据设置了多个数据并且有乱序声明。
int a1; //a : 全局未初始化变量
int a2;
int b1 = 4; //b: 全局已初始化变量
int b2 = 5;
static int c1; //c: 全局未初始化静态变量
static int c2;
static int d1 = 456; //d: 全局已初始化静态变量
static int d2 = 567;
const int e1 = 10; //全局常量
const int e2 = 9;
int b3 = 45;
const int e3 = 8;
static int d3 = 1293;
int a3;
static int c3;
int main()
{
static int f1;
static int g1 = 5678;
int h1 = 2;
static int f2;
static int g2 = 58;
const int k1 = 89;
int h2 = 4;
const int k2 = 85;
cout << "***********************" << endl;
cout << "global uninit" << endl;
printf("name: %s addr: %p\n", "a1", &a1);
printf("name: %s addr: %p\n", "a2", &a2);
printf("name: %s addr: %p\n", "a3", &a3);
cout << "global init" << endl;
printf("name: %s addr: %p\n", "b1", &b1);
printf("name: %s addr: %p\n", "b2", &b2);
printf("name: %s addr: %p\n", "b3", &b3);
cout << "global static uninit" << endl;
printf("name: %s addr: %p\n", "c1", &c1);
printf("name: %s addr: %p\n", "c2", &c2);
printf("name: %s addr: %p\n", "c3", &c3);
cout << "global static init" << endl;
printf("name: %s addr: %p\n", "d1", &d1);
printf("name: %s addr: %p\n", "d2", &d2);
printf("name: %s addr: %p\n", "d3", &d3);
cout << "global const" << endl;
printf("name: %s addr: %p\n", "e1", &e1);
printf("name: %s addr: %p\n", "e2", &e2);
printf("name: %s addr: %p\n", "e3", &e3);
cout << "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" << endl;
cout << "local static uninit" << endl;
printf("name: %s addr: %p\n", "f1", &f1);
printf("name: %s addr: %p\n", "f2", &f2);
cout << "local static init" << endl;
printf("name: %s addr: %p\n", "g1", &g1);
printf("name: %s addr: %p\n", "g2", &g2);
cout << "local" << endl;
printf("name: %s addr: %p\n", "h1", &h1);
printf("name: %s addr: %p\n", "h2", &h2);
cout << "local const" << endl;
printf("name: %s addr: %p\n", "k1", &k1);
printf("name: %s addr: %p\n", "k2", &k2);
cout << "***********************" << endl;
return 0;
}
结果输出如下
***********************
global uninit
name: a1 addr: 00479008
name: a2 addr: 0047900C
name: a3 addr: 00479010
global init
name: b1 addr: 0046E000
name: b2 addr: 0046E004
name: b3 addr: 0046E010
global static uninit
name: c1 addr: 00479018
name: c2 addr: 0047901C
name: c3 addr: 00479020
global static init
name: d1 addr: 0046E008
name: d2 addr: 0046E00C
name: d3 addr: 0046E014
global const
name: e1 addr: 0046F24C
name: e2 addr: 0046F250
name: e3 addr: 0046F254
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
local static uninit
name: f1 addr: 00479024
name: f2 addr: 00479028
local static init
name: g1 addr: 0046E018
name: g2 addr: 0046E01C
local
name: h1 addr: 0069FEB8
name: h2 addr: 0069FEB0
local const
name: k1 addr: 0069FEB4
name: k2 addr: 0069FEAC
***********************
从上面的输出可得到:
1.已初始化的全局普通变量(global init)与全局静态变量(global static init),他们是放在一起的,按照声明顺序排列。记为A区。
2.已初始化的局部静态变量放在A区后面,记为B区
3.全局常量区在B区的后面,记为C区。普通的常量需初始化,这应该大概就是它排在中间位置的原因吧。
4.全局未初始化变量排在C区后面,记为D区,虽然A区中的普通变量和静态变量是混合排序的,但是在BBS区中,全局常量还是做了点区分。
5.全局未初始化静态区排在D区后,记为E区。
6.局部未初始化静态变量放在E区后,记为F区。
7.局部常量与局部变量存放在栈区,局部变量可以不初始化
综上,可以看出
全局已初始化静态区:已初始化的全局普通变量,全局静态变量,局部静态变量
全局常量区:全局常量
BBS区:未初始化的全局普通变量,全局静态变量,局部静态变量。
扩展:
全局中:静态变量与普通变量的区别?
作用域不同,静态变量本文件使用,普通变量可跨文件使用。
局部中:静态变量与局部变量的区别?
存放位置不同,生存周期不同。数据区中的局部静态变量在程序运行过程中都存在,但是只有在声明了它的那个函数中才能访问它;而栈中的局部变量会随着函数的调用而入栈出栈,离开了栈,变量也就结束了生命;因为存放位置的不同,导致了它们生命周期的不同。
普通变量中:全局与局部的区别?
作用域不同,生存周期不同,全局变量函数运行期间一直存在,函数均可访问,局部变量生命周期在函数栈内,变量仅函数内可用。
静态变量中:全局与局部的区别?
作用域不同,虽然他们在程序运行的整个周期内都存在于数据区,但局部静态变量,仅只能在定义了它的函数内调用,而全局静态变量全局可用。