注意:我的编译环境为VC++6.0. 系统平台为: windows XP 不同的编译环境和操作系统可能有所不同.
#include <iostream>
using namespace std;
0012FF |
5 |
0012FF78 |
4 |
0012FF74 |
3 |
0012FF70 |
2 |
0012FF |
1 |
0012FF68 |
10 |
0012FF64 |
9 |
0012FF60 |
8 |
0012FF |
7 |
0012FF58 |
6 |
a[4]
a[3]
a[2]
a[1]
? a[0]
b[4]
b[3]
b[2]
b[1]
?b[0]
根据上面的图表我们可以看出:数据在内存中的存储情况。即编译器和系统在为变量分配是从高地址开始分配的.
分析代码:
int a[5] = {1,2,3,4,5};
我们定义了一个数组a,那么此时系统和编译器便从栈地址区找出一块空闲内存分配给数组a.然后数组a便在这块内存中从高地址开始存储,即a[4]--->a[0]
int b[5] = {6,7,8,9,10};
我们又定义了一个数组b,那么系统和编译器以同样的方法对待b,不过这次是接着a的结束地址往下开始分配(由高往低).
最后的结果便是上面的图表所列的情况,从上面表中我们可以看出b[5]便是a[0]单元,b[6]是a[1]单元.
所以输出结果便是2了.
也许有些朋友对这个在理解上有些困难,我们再来看一个简单的:
#include <iostream>
using namespace std;
int main()
{
int a = 2;
int b = 3;
int *p = &b;
cout << *p << endl;
cout << *(++p) << endl;
return 0;
}
输出结果:
3
2
我们可以使用:
cout << &a << endl;
cout << &b << endl;
来查看a,b在内存中的地址情况:
0012FF7C
0012FF78
可以看出a的地址高于b的地址.且他们之间差了4个字节,这是因为a占4个字节.
这样我们应该就可以理解为什么输出结果为3 2了。p开始指向变量b,即在变量p的内存空间中存有b的地址。我们输出*p,即输出b的值为3.而后我们输出*(++p)即现对p里面的内容+1,然后输出*p.
这里有一点提醒的是: +1操作并不是总是+1,它有它自己的单位,在这里它的单位为4个字节,即一个int型的大小.所以在p+1后就指向了变量a.所以输出结果就为2了.
好的,问题解决了,但是新的问题又来了。
那么全局变量,以及函数中的参数也是如此吗?
我们可以对上面的一段代码加上断点,对其进行调试然后查看各个变量的地址进行比较就可以看出。全局变量和函数参数在内存中的存储是由低地值到高地址的.这又是什么原因呢?
我们需要清楚的是:内存分为不同的区域用于不同的作用.
全局变量是放在全局区里的。函数的参数是放在堆区中的.对于这点可能有些朋友会不明白了,函数参数为什么会放到堆区呢?这是因为我们的函数是在程序运行中进行动态的调用的.在函数的编译阶段根本无法确定他会调用几次,会需要多少内存.即使可以确定那时候就为变量分配好内存着实也是一种浪费。所以编译器为函数参数选择动态的分配..即在每次调用函数时才为它动态的进行分配空间.
而那为什么这两个区域的变量在内存中的存储就是顺序的呢?
我想这个问题就是栈机制的影响吧.函数内部定义的非动态分配的,非静态变量都是放在栈区的.我们大家都清楚栈有着后进先出的特性.并且栈区不但要保存部分变量,还有保存函数的入口地址,断点地址,参数等.这种栈的机制对函数调用,中断都有着很重要的作用.
而在全局区,堆区中没有这种机制,也无需这种机制,也就顺序分配了.
评论