注意:这篇文章上次更新于935天前,文章内容可能已经过时。
这是一道百度的笔试题
问:关于下面的程序输出为:
- A:1
- B:2
- C:3
- D:编译无法通过
#include <iostream>
using namespace std;
void test(int a,int b,int c){
int *p = &b;
cout << *(p-1) << endl;
}
int main(){
test(1,2,3);
return 0;
}
正确答案是…
C
如果和你想的一样,那说明你已经掌握了这个知识点了。
第一眼看本来想选 D 的(我是个呆瓜🐽),后来想了一下(就是想了一下而已),决定选 A。
我对这道题还是比较好奇,于是笔试完用 OnlineGBD 敲了一下。
结果竟然是…!!!
一时之间不知道为什么,并且表示很吃惊,于是和同学讨论一下。
让我更是震惊,难道天底下只有我一个呆瓜吗😂
又简单聊几句勾起了我大脑深处尘封已久的对于知识的记忆。我想起了栈区地址和堆区地址生长方向的问题,但是记不清楚栈区是低地址向高地址生长还是高地址向低地址生长。又联想前大家总是说压栈,难道是低地址向高地址生长?可是和输出结果不相符啊。
于是简单测试一下。
结论很显然:
栈区向低地址生长,堆区向高地址生长
更多测试
既然已经测试到这了,干脆就复习的全一些,把各种变量都测试一下。
#include <iostream>
using namespace std;
static int p = 5;
static int q = 6;
const int m = 7;
const int n = 8;
void test(int a,int b,int c){
static int i = 2;
static int j = 3;
const int s = 4;
const int t = 5;
int* x = new int(a);
int* y = new int(b);
int* z = new int(c);
cout << "栈区地址:" << endl;
cout << &a << endl << &b << endl << &c << endl;
cout << "堆区地址:" << endl;
cout << &x << endl << &y << endl << &z << endl;
cout << "全局Const常量:" << endl;
cout << &m << endl << &n << endl;
cout << "局部const常量:" << endl;
cout << &s << endl << &t << endl;
cout << "全局静态变量:" << endl;
cout << &p << endl << &q << endl;
cout << "局部静态变量:" << endl;
cout << &i << endl << &j << endl;
cout << "字符串常量:" << endl;
cout << &"abc" << endl << &"efg" << endl;
}
int main()
{
test(1,2,3);
return 0;
}
代码的运行结果如下:
栈区地址:
0x7ffc3e31b75c
0x7ffc3e31b758
0x7ffc3e31b754
堆区地址:
0x7ffc3e31b770
0x7ffc3e31b778
0x7ffc3e31b780
全局Const常量:
0x561341be9008
0x561341be900c
局部const常量:
0x7ffc3e31b768
0x7ffc3e31b76c
全局静态变量:
0x561341beb010
0x561341beb014
局部静态变量:
0x561341beb018
0x561341beb01c
字符串常量:
0x561341be9093
0x561341be9097
可以得到几个基本结论:
- 栈区地址向下生长
- 堆区地址向上生长
- 局部进来变量和全局静态变量是放在一起的
- 字符串常量、静态变量和全局 const 常量处于整个内存空间的低地址,其余处于高地址。
由于局部 const 常量的生长方向是向上的,因此怀疑其可能存放在堆区(网上说其存放在栈区)。
总结
C/C++中内存分5大区:栈,堆,全局/静态存储区,常量存储区,代码区
Code Segment 代码区也称Text Segment,存放可执行程序的机器码。
Data Segment 存放已初始化的全局和静态变量, 常量数据(如字符串常量)。
BSS(Block started by symbol) 存放未初始化的全局和静态变量。(默认设为0)
Heap(堆) 从低地址向高地址增长。容量大于栈,程序中动态分配的内存在此区域。
Stack 栈从高地址向低地址增长。由编译器自动管理分配。程序中的局部变量、函数参数值、返回变量等存在此区域。