subject_46985.htm
来自「一些关于vc的问答」· HTM 代码 · 共 24 行
HTM
24 行
<p>
序号:46985 发表者:James.Q 发表日期:2003-07-16 13:27:08
<br>主题:[紧急求助]有谁真正了解外部变量的真实含义????
<br>内容:有这样一段程序:<BR>int a;<BR>int b = 10; <BR>void foo(char str[]) <BR>{ <BR> if (!str) return; <BR> str[0] = 'A'; <BR>} <BR><BR>int main() <BR>{ <BR> char *p = "Hello world!"; <BR> char *q = (char *)malloc(100); <BR><BR> //foo(p); <BR> //printf("%s\n", p); <BR> printf("&a: %xd\n",&a);<BR> printf("&b: %xd\n",&b);<BR>}<BR>编译运行后结果如下:<BR>&a: 405040d<BR>&b: 403010d<BR><BR>如果将int a;int b = 10;改成:int a; int b;<BR>则是如下的运行结果:<BR>&a: 405040d<BR>&b: 405050d<BR><BR>如果将int a = 0;int b = 10;改成:int a; int b;<BR>则是如下的运行结果:<BR>&a: 403010d<BR>&b: 403014d<BR><BR>我想问的是:<BR>1.a和b究竟是什么变量?(我认为是外部变量)他们究竟是怎么分配的?<BR>2.为什么对a,b进行初始化和不进行初始化打印结果有区别?<BR>3.外部变量的分配应该是在编译是确定的,为什么最后一个结果才是想要的(就是两个外部变量在一起)<BR>4.int a;和int a = 10有什么区别(int a 是在函数外面的,如果是在函数内部呢?)<BR>5.变量的申明和定义究竟是什么意思?(int a;是属于申明还是定义,我认为是申明加定义,并且编译是就初始化为0)<BR>6.将foo(p)的注释去掉,将会出现0x0040128e指令引用的0x00401293内存.该内存不能为writen....好像p是指向了代码段.为什么会这样,究竟参数是怎么入栈和变量是怎么分配的?<BR><BR>我刚学c语言(现在主要用的是java),希望各位大侠能指点迷津!!!
<br><a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p>
<hr size=1>
<blockquote><p>
<font color=red>答案被接受</font><br>回复者:Fang 回复日期:2003-07-16 14:41:39
<br>内容:-----我刚学c语言(现在主要用的是java),希望各位大侠能指点迷津!!! <BR>刚刚学习就问得这么有深度,佩服。<BR><BR>这个问题,一般来说,不同的编译器,不同的平台有不同的实现。或者说,这是编译器的内部问题,我们不用管太多。<BR><BR>以下回答基于win2000,vc6平台。<BR><BR>1.a和b究竟是什么变量?(我认为是外部变量)他们究竟是怎么分配的?<BR>当然是外部变量。<BR><BR>windows平台pe文件格式有两个数据段,.data 和 .rdata段。<BR>a,b都不是只读数据,当然应该在 .data中。<BR><BR>2.为什么对a,b进行初始化和不进行初始化打印结果有区别?<BR>3.外部变量的分配应该是在编译是确定的,为什么最后一个结果才是想要的(就是两个外部变量在一起)<BR><BR>这个问题让我汗颜,没有找到答案。只是发现初始化数据出现在.data段前部,未初始化放在.data后部。vc这样做是为什么,我不知道。<BR><BR>4.int a;和int a = 10有什么区别(int a 是在函数外面的,如果是在函数内部呢?)<BR>5.变量的申明和定义究竟是什么意思?(int a;是属于申明还是定义,我认为是申明加定义,并且编译是就初始化为0)<BR><BR>如果在函数内部,就不叫外部变量了,在.data段也找不到了,函数内部的局部变量(非static!)都是在栈中。<BR><BR>声明和定义有很大区别。细节不讲了。int a;既是声明也是定义。是不是初始化成0的问题,一般来说,...反正vc6是初始化成0的,我猜想这也是未初始化变量放在.data末尾的原因。<BR><BR>6.将foo(p)的注释去掉,将会出现0x0040128e指令引用的0x00401293内存.该内存不能为writen....好像p是指向了代码段.为什么会这样,究竟参数是怎么入栈和变量是怎么分配的?<BR><BR>有关这个事,我还发现了一系列的“怪事”:<BR>1,Debug版,foo(p);//去掉,“Hello World”出现在.rdata数据段(不是代码段)。所以可以解释非法访问(不可写)的问题。(你的“0x0040128e指令引用的0x00401293内存”似乎真的是在代码段?代码段也是只读的)<BR>2,Release版,foo(p);//去掉,“Hello World”出现在.data数据段,当然可以写。printf出现“Aello World”.<BR><BR>pe格式介绍文章网上可以找到。<BR>察看pe格式的工具dumpbin就可以了。vc自带工具。\bin目录下。
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:James.Q 回复日期:2003-07-16 17:01:17
<br>内容:非常感谢大侠的解答,我明白了一些问题.我上学时学过c,还是有过基础的,不过没用过vc,对win下编程不了解,这个程序还是我在win2k下用gcc编的,编控制台程序比较方便吧.我有运行了一下这个程序,结果如下:<BR>出现0x0040128e指令引用的0x00401293内存.该内存不能为writen....<BR>调试程序后,出现以下结果:<BR>0040128E mov byte ptr [eax],41h<BR>00401291 pop ebp<BR>00401292 ret<BR>00401293 dec eax<BR>00401294 ins byte ptr [edi],dx<BR>00401296 ins byte ptr [edi],dx<BR>00401297 outs dx,dword ptr [esi]<BR>00401298 and byte ptr [edi+6Fh],dh<BR>0040129B jb 00401309<BR>0040129D and dword ptr fs:[eax],eax<BR>004012A0 popad<BR>004012A2 cmp ah,byte ptr [eax]<BR>可以看出00401293 dec eax是指向程序代码.因为好像在linux下也会出现这个问题,所以我不知道参数是怎么传进去的.希望大侠能给予一条路.
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:Fang 回复日期:2003-07-16 18:18:16
<br>内容:访问出错的原因是str[0] = 'A'; 因为str[0]也就是“Hello World”中的'H',在代码段,代码段不可写,所以访问违例。----这就是我猜测的解释。<BR><BR>str的声明仅仅表明它是指针,p是指向“Hello World”的指针。和参数入栈没有关系。<BR><BR>如果char p[]="Hello World";那又不同了:p指向栈内的“Hello World”处。编译器会从不可读的代码段或者数据段把“Hello World”复制到栈内的空间p[]。<BR>
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?