(100)一个与初始化有关的问题!

Leslie_J 2005-08-12 11:25:14
今天看书,遇到了一个挺有趣的程序:
#include<iostream.h>
void main()
{
int m=5;
if(m==5)
goto abc;
//企图用goto语句跳过变量n的定义。
int n;
abc:
cout<<"m="<<m<<",n="<<n<<endl;
}
本以为该程序是不能通过编译的,可是它在VC++6.0中成功运行了,行运结果为:
m=5,n=-858993460
后来,我修改了一下:把int n;改为int n=10;再运行却失败了。错误是:initialization of 'n' is skipped by 'goto abc'。
为什么把int n;改为int n=10;就不能运行呢?
...全文
418 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
smjacky 2005-08-13
  • 打赏
  • 举报
回复
你这道题如果写成这样
#include<iostream.h>
void main()
{
int m=5;
int n;
if(m==5)
goto abc;
{
n = 100;
}
abc:
cout<<"m="<<m<<",n="<<n<<endl;
}

那么输出的结果也是 m=5,n=-858993460
而且编译的时候不会有警告的

你的第一种情况虽然能运行,但是编译的时候还是有警告信息的

smjacky 2005-08-13
  • 打赏
  • 举报
回复
goto 语句不能向前跳过变量的声明语句,比如这样是错误的
goto label:

int n = 100;
//... code using n;

label:

正确的做法是把声明语句和使用该声明的语句放在一个语句块内,比如这样就可以运行
goto label:
{
int n = 100;
//... code using n;
}
label:
A1027 2005-08-13
  • 打赏
  • 举报
回复
同意第二位的解释!
jixingzhong 2005-08-13
  • 打赏
  • 举报
回复
恩 如果只是声明,也许会通过的。
但是也有可能不行,因为程序并不知道这个被条过的定义,在后面的程序中是不是要被使用 ...

K 2005-08-13
  • 打赏
  • 举报
回复
只是声明可以这样做,可能编译器看到声明就在符号表里预留空间,而赋值是运行期间的,编译器无法控制,所以报错。
编译器原理我的不知道是什么,只是我的猜测。- -;
Leslie_J 2005-08-13
  • 打赏
  • 举报
回复
虽然问题没有完全解决,还是谢谢大家!
接分吧~~~~!
mituzhishi 2005-08-13
  • 打赏
  • 举报
回复
结帖吧,以后不写这种有歧义的程序就行了;

没什么好处,可读性还差。
Leslie_J 2005-08-13
  • 打赏
  • 举报
回复
谢谢大家.
今天,我又对第一个程序作出了一点看上去无伤大雅的修改,在VC++6.0上调试:
把int n;改成{int n;}即整个程序是:
#include<iostream.h>
void main()
{
int m=5;
if(m==5)
goto abc;
//企图用goto语句跳过变量n的定义。
{int n;}
abc:
cout<<"m="<<m<<",n="<<n<<endl;
}
我以为这个程序与第一个程序的运行结果会一样,事实却不然.
真正的结果是出错了,错误是:'n' : undeclared identifier
我更加不解,这到底是怎么一回事呢?
hoya5121 2005-08-13
  • 打赏
  • 举报
回复
知道声明和初始化时分别做的那些工作就知道答案了。。
foochow 2005-08-13
  • 打赏
  • 举报
回复
。net上2个都能编译成功,2个都不能运行。。。
ifeelhappy 2005-08-13
  • 打赏
  • 举报
回复
只是比较纳闷的是,跳过了 int n;那么n就没有定义,程序又如何识别printf中的n 呢?
我觉得,程序执行到printf语句,当它需要n的值得时候,它可能就会回去程序中找,看看有没有n被定义的地方,如果有,它就输出它声明的时候占用的地址上存放的值,这在程序员看来不合理,但编译器无法报错,因为编译器的源程序中可能没有考虑到这种错误。但是编译器可以看到n在被跳过的语句中被赋值是不合理的,就要报错。自己的想法而已。主要思想就是编译器也是人编的,也有漏洞,也有不合理的地方,不然要那么多维护人员干什么呢?
caocheng8230 2005-08-13
  • 打赏
  • 举报
回复
只是声明可以这样做,可能编译器看到声明就在符号表里预留空间,而赋值是运行期间的,编译器无法控制,所以报错。
caocheng8230 2005-08-13
  • 打赏
  • 举报
回复
你这种情况我在switch中也遇到过的,
int i=0;
switch(i)
{
case 0:
int c;
break;
case 1:
break;
}
没有错
int i=0;
switch(i)
{
case 0:
int c=3;
break;
case 1:
break;
}
有错
N_thread 2005-08-13
  • 打赏
  • 举报
回复
C++的编译器比较奇怪,难怪C语言要求都在开始把声明都写出来。
lujun-cc 2005-08-13
  • 打赏
  • 举报
回复
楼主的这个问题,比较有意思,估计要涉及到C++的模型中去了,而且这个也和编译器有很大关系。

我使用VC6的编译器,编译器提示:“error c2362:initialization of 'n' is skipped by 'goto abc'”

而VC7.1的编译器,则可以顺利通过编译,而且可以执行,只不过打印出的n值是不确定的。

然而,据说VC7.1的编译器对C++的标准支持的VC6的要好,那么也就是说,在标准中允许有这种作法,只是比较纳闷的是,跳过了 int n;那么n就没有定义,程序又如何识别printf中的n 呢?

mituzhishi 2005-08-12
  • 打赏
  • 举报
回复
goto是执行时候跳过,对编译没有太大影响,起码执行与编译不是一回事。

第一次编译通过是因为n为局部变量,默认不初始化,结果出现了莫名其妙的-858993460

第二次编译不通过是因为显式初始化了n,编译器认识到执行时候会跳过,所以抱错。

至于编译器的内部实现细节我也不是很懂,仅发表愚见,还望批评指正。
「已注销」 2005-08-12
  • 打赏
  • 举报
回复
按理说这样goto是不行的,可能VC的编译器有所不同吧。

65,213

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧