以下来自新浪博客的转载:
1:为何不提倡使用goto语句?
渊源(来自wikipedia):
GOTO是一条可以在许多计算机编程语言中找到的语句。它是英文单词go和to的组合。当执行这条语句的时候,它将控制流程无条件地转到另一条语句(也叫"跳转")。跳转语句需要指明标记,在不同语言中,标记可以是标识符或行号。在机器码级别,goto是一种分支的形式。
在一些语言中,可以不用显示地使用goto关键字而实现同样的功能,例如break或continue关键字可以跟随一个标识符。SNOBOL语言支持一种语句的后缀形式,可以在本条语句执行完毕后实现无条件跳转。
GOTO语句被大部分高级语言支持,只有很少的高级语言不支持GOTO语句。例如,goto是一个Java语言的保留字,但是不允许使用。例如Pascal中没有Goto,但可用procedure执行一外加语法。
GOTO语句一直是批评和争论的目标,主要的负面影响是使用GOTO语句使程序的可读性变差,甚至成为不可维护的“面条代码”。随着结构化编程在二十世纪六十年代到七十年代变得越来越流行,许多计算机科学家得出结论,即程序应当总是使用被称为“结构化”控制流程的命令,如循环以及if-then-else语句来替代GOTO。甚至在今天,许多程序风格编码标准禁止使用GOTO语句。为GOTO语句辩护的人认为,加以限制地使用GOTO语句不会导致低质量的代码,并且声称在许多编程语言中,一些任务如果不使用一条或多条GOTO语句是无法被直接实现的。如有限状态自动机的实现、跳出嵌套循环以及异常处理。
大概最著名的对于GOTO的批评是艾兹格·迪杰斯特拉(Edsger Wybe Dijkstra)在1968年的一篇名称为《GOTO陈述有害论(英语:Go To Statement Considered Harmful)》的论文。[2]迪杰斯特拉认为不加限制地使用GOTO语句应当从高级语言中废止,因为它使分析和验证程序正确性(特别是涉及循环)的任务变得复杂。另外一种观点高德纳的Structured Programming with go to Statements
这些批评在一些编程语言的设计上起到了效果。虽然Ada语言的设计者在二十世纪七十年代晚期意识到了对于GOTO的批评,这条语句仍旧被包含进去,主要是用来支持自动生成那些goto语句必不可少的代码。[4]但是,作为goto语句目的地的标签必须使用双尖括号括起来(如:<<Start_Again>>),而这个语法在其他语言中都不被使用。这使得检查程序中goto目的地的存在变得容易。goto语句本身使用简单的形式goto
原因: GOTO语句使程序的静态结构和动态结构不一致,从而使程序难以理解,难以查错。
有人认为GOTO语句使用起来比较灵活,而且有些情形能提高程序的效率。
1974年,D·E·克努斯对于GOTO语句争论作了全面公正的评述,其基本观点是:不加限制地使用GOTO语句,特别是使用往回跳的GOTO语句,会使程序结构难于理解,在这种情形,应尽量避免使用GOTO语句。但在另外一些情况下,为了提高程序的效率,同时又不至于破坏程序的良好结构,有控制地使用一些GOTO语句也是必要的。用他的话来说就是:“在有些情形,我主张删掉GOTO语句;在另外一些情形,则主张引进GOTO语句。”
后来,G·加科皮尼和C·波姆从理论上证明了:任何程序都可以用顺序、分支和重复结构表示出来。这个结论表明,从高级程序语言中去掉GOTO语句并不影响高级程序语言的编程能力,而且编写的程序的结构更加清晰。
goto语句的结果:在C/C++等高级编程语言中保留了goto语句,但被建议不用或少用。在一些更新的高级编程语言,如Java不提供goto语句,它虽然指定goto作为关键字,但不支持它的使 用,使程序简洁易读;尽管如此后来的c#还是支持goto语句的,goto语句一个好处就是可以保证程序存在唯一的出口,避免了过于庞大的if嵌套。
可以考虑使用goto的情形:1.从多重循环中直接跳出 ;2. 出错时清除资源; 3.可增加程序的清晰度的情况。
不加限制地使用goto:破坏了清晰的程序结构,使程序的可读性变差,甚至成为不可维护的"面条代码"。经常带来错误或隐患,比如它可能跳过了某些对象的构造、变量的初始化、重要的计算等语句。
goto语句问题的提出直接推动了结构化程序设计(structured programming)的思想和程序设计方法学的诞生和发展。结构化程序设计方法引入了工程思想和结构化思想,使大型软件的开发和编程都得到了极大的改善。结构化程序设计方法的主要原则可以概括为自顶向下,逐步求精,模块化,限制使用goto语句。
下列关于使用goto语句的原则可以供读者参考。 1) 使用goto语句只能goto到同一函数内,而不能从一个函数里goto到另外一个函数里。 2) 使用goto语句在同一函数内进行goto时,goto的起点应是函数内一段小功能的结束处,goto的目的label处应是函数内另外一段小功能的开始处。 3) 不能从一段复杂的执行状态中的位置goto到另外一个位置,比如,从多重嵌套的循环判断中跳出去就是不允许的。 4)应该避免像两个方向跳转。这样最容易导致"面条代码"。
2:网友热心回答
goto并不是不能用,关键是goto指向的标签必须在goto这行的后面。
盲目禁用goto是不对的。
见杰拉尔德·温伯格《理解专业程序员》
如果要做软件开发的话,特别是团队的话,为了将来项目的维护和让代码通俗易懂,最好不要用goto;
goto会影响编译器优化,还有九成的goto都可以转换成不用goto的方式
如果GOTO的语句在后面就不会出现死循环!
如果GOTO的语句在前面就很容易死循环!!!
还有,GOTO
所以,一般不用GOTO!!
因为那会扰乱编程结构次序
3:
正面:
goto语句在C/C++语言中可谓是“臭名昭著”,乃至有的书(或公司的编程规范)提出禁用goto语句的说法。其结果就是,造成有的程序员一看到goto语句在某程序中被使用,就本能地认为这个程序写得很“垃圾”。此外,也使得有些程序员因为使用了goto语句而觉得自己很不专业。其实,凡事都不能太偏激,goto语句运用得好能大大地简化程序,以及提高程序的可读性和可维护性。在开始示例其好处之前,先用一些统计数据来说明goto语句并没有因为“臭名昭著”而被抛弃,这些统计数据可能并不是百分之百的精确,但很具有说服力。对于操作系统,Linux-2.6.21内核使用了20,333个goto语句,VxWorks-6.2则使用了9142个,最后941个goto语句被运用到了rtems-4.9.2中;另外,glibc-2.9库使用了1750个goto语句。所有这些统计数据都表明,goto语言并没有想象的那样可怕而招到禁用,其关键在于 —— 恰当地运用它。
转载来自:http://blog.sina.com.cn/s/blog_6908039c0101f5hx.html
以下来自csdn博客的转载:
goto只能在函数体内跳转,不能跳到函数体外的函数。即goto有局部作用域,需要在同一个栈内。
需要在要跳转到的程序段起始点加上标号。如下例中的part2。
1.goto 语句可用于跳出深嵌套循环
- #include<iostream>
- using namespace std;
- int main()
- {
- for(int i=0;i<10;i++)
- for(int j=0;j<10;j++)
- for(int k=0;k<10;k++)
- {
- cout<<i*j*k<<" ";
- if(216==i*j*k)
- goto part2;//break是跳不出多重循环的
- }
- cout<<"此处被省略"<<endl;
- part2:
- cout<<"part2"<<endl;
- system("pause");
- }
#include<iostream>
using namespace std;
int main()
{
for(int i=0;i<10;i++)
for(int j=0;j<10;j++)
for(int k=0;k<10;k++)
{
cout<<i*j*k<<" ";
if(216==i*j*k)
goto part2;//break是跳不出多重循环的
}
cout<<"此处被省略"<<endl;
part2:
cout<<"part2"<<endl;
system("pause");
}
2.goto语句可以往后跳,也可以往前跳
- #include<iostream>
- using namespace std;
- int main()
- {
- int x,sum=0;
- //定义标号L1
- L1: cout<<"x=";
- cin>>x;
- if (x==-1)
- goto L2; //当用户输入-1时,转到L2语句处
- else
- sum+=x;
- goto L1; //只要用户没有输入-1,则转到L1语句处,程序一直将用户的输入默默地累加到变量sum中。
- //定义标号L2
- L2: cout<<"sum="<<sum<<endl;//一旦转到L2,将输出累计结果,程序运行结束。
- system("pause");
- }
#include<iostream>
using namespace std;
int main()
{
int x,sum=0;
//定义标号L1
L1: cout<<"x=";
cin>>x;
if (x==-1)
goto L2; //当用户输入-1时,转到L2语句处
else
sum+=x;
goto L1; //只要用户没有输入-1,则转到L1语句处,程序一直将用户的输入默默地累加到变量sum中。
//定义标号L2
L2: cout<<"sum="<<sum<<endl;//一旦转到L2,将输出累计结果,程序运行结束。
system("pause");
}
3.也可以跳出switch,或者在case之间进行跳转
如:
- #include<iostream>
- using namespace std;
- int main()
- {
- char a;
- L1:
- cout<<"请输入一个字符"<<endl;
- cin>>a;
- switch(a)
- {
- case 'a':
- cout<<"case a"<<endl;
- goto L1;
- //break;
- L2:
- case 'b':
- cout<<"case b"<<endl;
- break;
- case 'c':
- cout<<"case c"<<endl;
- // break;
- goto L2;
- default:
- break;
- }
- system("pause");
- }
#include<iostream>
using namespace std;
int main()
{
char a;
L1:
cout<<"请输入一个字符"<<endl;
cin>>a;
switch(a)
{
case 'a':
cout<<"case a"<<endl;
goto L1;
//break;
L2:
case 'b':
cout<<"case b"<<endl;
break;
case 'c':
cout<<"case c"<<endl;
// break;
goto L2;
default:
break;
}
system("pause");
}