



全文预览已结束
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
对于许多C/C+初学者,往往知道static变量只是被初始化一次,对于const变量,只知道他的值是不能被修改的,但是对于其实现却不知所有然。这里我以VC6.0 SP6为平台,揭开其编译器实现原理。下面看一段程序: 引用:#include void fun(int i) static int n = i ; int *p = &n ; cout n 0; -i) fun(i) ; return 0;程序的输出结果是: 引用:10111213141516171819下面我们调试一下,看下编译器如何实现:我们在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 ./ n0042E060 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 . / n10042E060 00 00 00 00 . / n20042E064 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 void fun(int i) static int n1 = 0x12345678 ; int *p = &n1 ; cout *p 0; -i) fun(i) ; return 0;当指针取到值之后,我们结束调试。我这里的地址值是0x0042ad64。好了,我们结束调戏,用winhex打开生成的可执行文件,按Alt+g跳到n的地址,这里要减去0x400000,也就是2ad64。是不是看到我们的初值了。因为intel使用的是小端法,所以我们看到的值是反过来的。下面我们再来探索一下const的原理;下面看一个程序段 引用:#include int main(void) const int n = 1 ; int *p = (int *)&n ; *p = 0 ; cout n endl ; cout *p endl ; return 0;我们执行一下,结果是不是和我们所期望的不同呢,我们在第一行下断点,一条一条的执行。确认每一步操作是否正确。当执行到*p = 0的时候我们发现n内存所在的值已经变成0了,但是为什么执行结果令我们大失所望呢?我们按Alt +8打开汇编窗口。 引用:7: cout n endl ;0041161E push offset ILT+40(endl) (0040102d)00411623 push 100411625 mov ecx,offset cout (0042e070)0041162A call ostream:operator (004012a0)0041162F mov ecx,eax00411631 call ILT+30(ostream:operator) (00401023)8: cout *p endl ;00411636 push offset ILT+40(endl) (0040102d)0041163B mov edx,dword ptr ebp-80041163E mov eax,dword ptr edx00411640 push eax00411641 mov ecx,offset cout (0042e070)00411646 call ostream:operator (004012a0)0041164B mov ecx,eax004
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 但协议不一定是合同
- 合伙造林协议合同
- 阳江复印机租赁协议合同
- 合同协议字体模板
- 怎样写退出合同协议
- 烧虾子合同协议
- 外委合同解除协议
- 软件招商合同协议书范本
- 转让房租合同协议书范本
- 集装箱施工合同协议范本
- 教育教学能力大赛实施报告
- 风电项目达标投产场内集电线路工程电力电缆部分质量检查验收表
- DL∕T 5210.2-2018 电力建设施工质量验收规程 第2部分:锅炉机组
- 110kV线路铁塔组立专项施工方案
- 2024北京海淀区初二(下)期末物理及答案
- 基层医疗卫生机构6S管理标准1-1-5
- 2018容器支座第1部分:鞍式支座
- 中考总复习:无刻度直尺作图2
- 第5课《弘扬劳动精神劳模精神工匠精神》第2框《践行劳动精神劳模精神工匠精神》-【中职专用】《职业道德与法治》同步课堂课件
- 重点关爱学生帮扶活动记录表
- 江苏省苏州市2023-2024学年四年级下学期期中综合测试数学试卷(苏教版)
评论
0/150
提交评论