欢迎来到天天文库
浏览记录
ID:20486929
大小:167.90 KB
页数:11页
时间:2018-10-12
《初探编译器staticconst之实现原理》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库。
1、初探编译器static、const之实现原理2009-12-1815:32:57我来说两句收藏我要投稿[字体:小大]作者:evilknight摘自邪恶八进制编译环境:WinXPsp2+VC6.0SP6对于许多C/C++初学者,往往知道static变量只是被初始化一次,对于const变量,只知道他的值是不能被修改的,但是对于其实现却不知所有然。这里我以VC6.0SP6为平台,揭开其编译器实现原理。下面看一段程序:引用:#include〈iostream.h〉voidfun(inti){staticintn=i;int*p=&n
2、;cout«n<0;—i){fun(i);)return0;}程序的输出结果是:引用:10111516171819下面我们调试一下,看下编译器如何实现:我们在fun函数的第一行没一个断点。staticintn=i;所在行,按F5。按Alt+6打开Memory。按F10单步执行,当p有值的时候,我们将他的值拖到Memory窗口,这时就会转到n所在的内存地址,可是这
3、时static己经初始化了,我们不知道编译器对他做了什么操作了。这时我们重新开始调试,一般n的内存地址不会变的,还是在那里。我这里以我这边的地址为例:引用:0042E05800000000....0042E05C00000000....//中间这个为n的内存地址0042E06000000000….我们按F10单步执行一下一条语句(staticintn=i;)引用:0042E05801000000....0042E05C0A000000....//n0042E06000000000....执行完这条语句之后,除了n有了初值,上
4、面有内存空间也有了变化。我们接着按F5直接执行到那个断点处,再单步执行一下,发现这次只是n的值有变化,所以我们猜测上面的那个位可能是static的标志位,如果是0的话,说明没有初始化,如果是1的话,说明已经初始化了,I次再进来的时候就不用初始化了,为了验证我们的猜测,我们现在在函数里面加几句语言,修改那个值。引用:voidfun(inti){staticintn=i;int*p=&n;cout«n<5、句,我们执行一下,是不是发现执行结果己经和上面的不同了,每次进函数都会对staticintn进行赋初值操作。下面我们再來看2个static类型的情况,在上面的代码中,我们再加一个static变量;引用:voidfun(inti){staticintnl=i;staticintn2=i;int*p=&nl;cout«nl«endl;++nl;////等下我们要在这写代码,让staticintn//每次进这个函数都初始化一次—P:氺p=0;//}还是继续调戏。二个static变量初始化之前内存里面的值引用:0042E0500006、00000•♦•♦0042E05400000000•♦•♦0042E05800000000•♦•♦0042E05C00000000….//nl0042E06000000000....//n20042E06400000000•…当执行完staticint成这样了引用:0042E05801000000•♦•♦0042E05C0A000000•♦•♦0042E06000000000....接着我们再单步执行内存的值变成这样。引用i;语句之后,内存的值变0042E05803000000....0042E05C0A000000....7、0042E060OA000000....这样就很明显了,编译器分别用一位來表示一个static变量是否已经始化。上面是对于用变量对static进行初始化,对于用常量初始化的情况是怎么样的呢?我们将上面的代码改成:引用:^includevoidfun(inti){staticintnl=0x12345678;int*p=&nl;cout<<*p«endl;}intmain(void){for(inti(10);i>0;—i){fun(i);}return0;}当指针取到值之后,我们结束调试。我这里的地址8、值是0x0042ad64。好了,我们结束调戏,用winhex打开生成的可执行文件,按Alt+g跳到n的地址,这里要减去0x400000,也就是2ad64o是不是看到我们的初值了。因为intel使用的是小端法,所以我们看到的值是反过来的。下面我们再來探索一下const的原理;下面看一个程序段
5、句,我们执行一下,是不是发现执行结果己经和上面的不同了,每次进函数都会对staticintn进行赋初值操作。下面我们再來看2个static类型的情况,在上面的代码中,我们再加一个static变量;引用:voidfun(inti){staticintnl=i;staticintn2=i;int*p=&nl;cout«nl«endl;++nl;////等下我们要在这写代码,让staticintn//每次进这个函数都初始化一次—P:氺p=0;//}还是继续调戏。二个static变量初始化之前内存里面的值引用:0042E050000
6、00000•♦•♦0042E05400000000•♦•♦0042E05800000000•♦•♦0042E05C00000000….//nl0042E06000000000....//n20042E06400000000•…当执行完staticint成这样了引用:0042E05801000000•♦•♦0042E05C0A000000•♦•♦0042E06000000000....接着我们再单步执行内存的值变成这样。引用i;语句之后,内存的值变0042E05803000000....0042E05C0A000000....
7、0042E060OA000000....这样就很明显了,编译器分别用一位來表示一个static变量是否已经始化。上面是对于用变量对static进行初始化,对于用常量初始化的情况是怎么样的呢?我们将上面的代码改成:引用:^includevoidfun(inti){staticintnl=0x12345678;int*p=&nl;cout<<*p«endl;}intmain(void){for(inti(10);i>0;—i){fun(i);}return0;}当指针取到值之后,我们结束调试。我这里的地址
8、值是0x0042ad64。好了,我们结束调戏,用winhex打开生成的可执行文件,按Alt+g跳到n的地址,这里要减去0x400000,也就是2ad64o是不是看到我们的初值了。因为intel使用的是小端法,所以我们看到的值是反过来的。下面我们再來探索一下const的原理;下面看一个程序段
此文档下载收益归作者所有