当前位置:七道奇文章资讯安全技术网络技术
日期:2009-12-18 01:20:00  来源:本站整理

初探编译器static、const之实现原理[网络技术]

赞助商链接



  本文“初探编译器static、const之实现原理[网络技术]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:

作者:evilknight摘自险恶八进制

编译环境: WinXP sp2 + VC6.0 SP 6

        关于很多C/C++初学者,常常知道static变量只是被初始化一次,关于const变量,只知道他的值是不能被改正的,但是关于其实现却不知全部然.这里我以VC6.0 SP6为平台,揭开其编译器实现原理.
下面看一段程序: 引用:
#include <iostream.h>
void fun(int i)
{
    static int n = i ;
    int *p = &n ;
    cout << n << endl ;
    ++n ;
    //
    // 等下我们要在这写代码,让static int n
    // 每次进这个函数都初始化一次
    //
}
int main(void)
{
    for (int i(10); i > 0; --i)
    {
        fun(i) ;
    }
    return 0;
}程序的输出后果是: 引用:
10
11
12
13
14
15
16
17
18
19下面我们调试一下,看下编译器若何实现:
我们在fun函数的第一行设一个断点.static int n = i ;所在行,按F5.
按Alt+6翻开Memory.按F10单步履行,当p有值的时刻,我们将他的值拖到Memory窗口,这时就会转到n所在的内存地址,但是这时static已经初始化了,我们不知道编译器对他做了什么操作了.这时我们重新开始调试,普通n的内存地址不会变的,还是在那边.
我这里以我这边的地址为例: 引用:
0042E058 00 00 00 00 ....
0042E05C 00 00 00 00 .... // 中间这个为n的内存地址
0042E060 00 00 00 00 ....我们按F10单步履行一下一条语句(static int n = i ;) 引用:
0042E058 01 00 00 00 ....
0042E05C 0A 00 00 00 ....// n
0042E060 00 00 00 00 ....履行完这条语句之后,除了n有了初值,上面有内存空间也有了改变.
我们接着按F5直接履行到那个断点处,再单步履行一下,发现这次只是n的值有改变,所以我们猜想上面的那个位大概是static的标志位,假如是0的话,阐明没有初始化,假如是1的话,阐明已经初始化了,下次再进来的时刻就不用初始化了,为了考证我们的猜想,我们目前在函数里面加几句语言,改正那个值. 引用:
void fun(int i)
{
    static int n = i ;
    int *p = &n ;
    cout << n << endl ;
    ++n ;
    //
    // 等下我们要在这写代码,让static int n
    // 每次进这个函数都初始化一次
    --p ;
    *p = 0 ;
    //
}写完上面二句,我们履行一下,是不是发现履行后果已经和上面的差别了,每次进函数城市对static int n举行赋初值操作.

下面我们再来看2个static范例的情形,在上面的代码中,我们再加一个 static变量; 引用:
void fun(int i)
{
    static int n1 = i ;
    static int n2 = i ;
    int *p = &n1 ;
    cout << n1 << endl ;
    ++n1 ;
    //
    // 等下我们要在这写代码,让static int n
    // 每次进这个函数都初始化一次
    --p ;
    *p = 0 ;
    //
}还是持续调戏.
二个static变量初始化之前内存里面的值 引用:
0042E050 00 00 00 00 ....
0042E054 00 00 00 00 ....
0042E058 00 00 00 00 ....
0042E05C 00 00 00 00 .... // n1
0042E060 00 00 00 00 .... // n2
0042E064 00 00 00 00 ....当履行完static int n1 = i ;语句之后,内存的值变成这样了 引用:
0042E058 01 00 00 00 ....
0042E05C 0A 00 00 00 ....
0042E060 00 00 00 00 ....接着我们再单步履行
内存的值变成这样. 引用:
0042E058 03 00 00 00 ....
0042E05C 0A 00 00 00 ....
0042E060 0A 00 00 00 ....这样就很明显了,编译器辨别用一位来表示一个static变量能否已经始化.

上面是关于用变量对 static举行初始化,关于用常量初始化的情形是怎么样的呢?
我们将上面的代码改成: 引用:
#include <iostream.h>
void fun(int i)
{
    static int n1 = 0x12345678 ;
    int *p = &n1 ;
    cout << *p << endl ;
}
int main(void)
{
    for (int i(10); i > 0; --i)
    {
        fun(i) ;
    }
    return 0;
}当指针取到值之后,我们完毕调试.我这里的地址值是0x0042ad64.
好了,我们完毕调戏,用winhex翻开生成的可履行文件,按Alt+g跳到n的地址,这里要减去0x400000,也就是2ad64.是不是看到我们的初值了.
因为intel利用的是小端法,所以我们看到的值是反过来的.

[1] [2]  下一页


  以上是“初探编译器static、const之实现原理[网络技术]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
  • 初探编译器static、const之实现原理
  • 本文地址: 与您的QQ/BBS好友分享!
    • 好的评价 如果您觉得此文章好,就请您
        0%(0)
    • 差的评价 如果您觉得此文章差,就请您
        0%(0)

    文章评论评论内容只代表网友观点,与本站立场无关!

       评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
    Copyright © 2020-2022 www.xiamiku.com. All Rights Reserved .