goto语句为啥不受待见

什么是goto语句

goto语句被称为C语言中的跳转语句。用于无条件跳转到其他标签。它将控制权转移到程序的其他部分。
goto
语句一般很少使用,因为它使程序的可读性和复杂性变得更差。
语法

goto label;

goto语句示例

让我们来看一个简单的例子,演示如何使用C语言中的goto语句。

打开Visual Studio创建一个名称为:goto的工程,并在这个工程中创建一个源文件:goto-statment.c,其代码如下所示 -

#include <stdio.h>  void main() {int age;    gotolabel:printf("You are not eligible to vote!");printf("Enter you age:");scanf("%d", &age);if (age < 18) {goto gotolabel;    }else {printf("You are eligible to vote!");    }}

执行上面代码,得到以下结果

You are not eligible to vote!Enter you age:12You are not eligible to vote!Enter you age:18You are eligible to vote!

为什么它这么不受待见?

二十几年前,当计算机编程尚处于起步阶段时,程序流程是由“GOTO”语句来控制。该类语句允许程序员对当前代码行断行,而直接进入另一个不同的代码段。

编程语言终究开始引入了函数的概念,即允许程序对代码进行断行。如果已经完成,不再使用goto语句来表示代码的断行。函数调用后,函数将回到下一条指令。其中一个主要的原因是,一个遍布goto语句的程序会让让人很难抓住重心,不便于对程序的理解和维护。

用函数控制流程

而wikipedia上的解释就是,GOTO语句一直是批评和争论的目标,主要的负面影响是使用GOTO语句使程序的可读性变差,甚至成为不可维护的「面条代码」。随着结构化编程在二十世纪六十年代到七十年代变得越来越流行,许多计算机科学家得出结论,即程序应当总是使用被称为「结构化」控制流程的命令,如迴圈以及if-then-else语句来替代GOTO。
甚至在今天,许多程序风格编码标准禁止使用GOTO语句。为GOTO语句辩护的人认为,加以限制地使用GOTO语句不会导致低质量的代码,并且声称在许多编程语言中,一些任务如果不使用一条或多条GOTO语句是无法被直接实现的。如有限状态自动机的实现、跳出嵌套循环以及异常处理。

大概最著名的对于GOTO的批评是艾兹格·迪杰斯特拉(Edsger Wybe Dijkstra)在1968年的一篇名稱為《GOTO陳述有害論》的論文。[2]迪杰斯特拉认为不加限制地使用GOTO语句应当从高级语言中废止,因为它使分析和验证程序正确性(特别是涉及循环)的任务变得复杂。
另外一种观点出现在高德纳的Structured Programming with go to Statements [3]中,文章分析了许多常见编程任务,然后发现其中的一些使用GOTO将得到最理想的结构。

这些批评在一些编程语言的设计上起到了效果。虽然Ada语言的设计者在二十世纪七十年代晚期意识到了对于GOTO的批评,这条语句仍旧被包含进去,主要是用来支持自动生成那些goto语句必不可少的代码。
[4]但是,作为goto语句目的地的标签必须使用双尖括号括起来(如:<<Start_Again>>),而这个语法在其他语言中都不被使用。这使得检查程序中goto目的地的存在变得容易。goto语句本身使用简单的形式goto Start_Again;.

另外,有许多不同的语言构成可以看作是goto的变形:

限制的GOTO
许多语言,如C语言和Java,提供了相关的控制流语句,如break和continue,它们都是有效地被限制的goto语句。它们的作用是无条件跳转,但是只能够跳到循环块结束的位置——继续进入下一循环(continue)或者结束循环(break)
switch/case结构
C语言、C++和Java中的switch语句高效地实现了一个多路goto,跳转目标由表达式的值来选择。

这也导致了我们没有不得不使用goto的理由。

针对这些,导致目前goto的使用情况是这样的:

goto语句的结果:在C/C++等高级编程语言中保留了goto语句,但被建议不用或少用。在一些更新的高级编程语言,如Java不提供goto语句,它虽然指定goto作为关键字,但不支持它的使 用,使程序简洁易读;尽管如此后来的c#还是支持goto语句的,goto语句一个好处就是可以保证程序存在唯一的出口,避免了过于庞大的if嵌套。

另一方面,goto语句只是不提倡,当然不是禁用,那么在什么情况下可以使用goto语句呢?

可以考虑使用goto的情形:

  1. 从多重循环中直接跳出 ;
  2. 出错时清除资源;
  3. 可增加程序的清晰度的情况。

不加限制地使用goto:破坏了清晰的程序结构,使程序的可读性变差,甚至成为不可维护的"面条代码"。经常带来错误或隐患,比如它可能跳过了某些对象的构造、变量的初始化、重要的计算等语句。

下列关于使用goto语句的原则可以供读者参考。

1) 使用goto语句只能goto到同一函数内,而不能从一个函数里goto到另外一个函数里。  

2) 使用goto语句在同一函数内进行goto时,goto的起点应是函数内一段小功能的结束处,goto的目的label处应是函数内另外一段小功能的开始处。  

3) 不能从一段复杂的执行状态中的位置goto到另外一个位置,比如,从多重嵌套的循环判断中跳出去就是不允许的。  

4)应该避免像两个方向跳转。这样最容易导致"面条代码"。

阅读过linux内核代码的同学应该注意到,linux内核代码里面其实有不少地方用了goto语句,但是你会发现,它的使用非常谨慎,基本都遵循上面提到的几个原则。

原文地址:https://www.cnblogs.com/vvsblog/p/11526721.html

时间: 2024-10-12 13:40:52

goto语句为啥不受待见的相关文章

C语言禁术——goto语句

goto语句是一种无条件转移语句,goto 语句的使用格式为:     goto  语句标号;其中标号是一个有效的标识符,这个标识符加上一个":"(冒号)一起出现在函数内某处,执行goto语句后,程序将跳转到该标号处并执行其后的语句. 另外标号必须与goto语句同处于一个函数中,但可以不在一个循环层中.通常goto语句与if条件语句连用,当满足某一条件时,程序跳到标号处运行. goto语句通常不用,主要因为它将使程序层次不清,且不易读,但在多层嵌套退出时,用goto语句则比较合理. 大

goto语句引起的crosses initialization of XXX

1. 背景 goto语句虽然目前已经不提倡使用,但是用起来还是很方便,尤其是老代码中见的比较多. 在改动有goto语句的老代码时需要特别注意,是否跳过来资源的释放.有用变量的初始化等等. 很久之前写c程序时,有些提交系统要求变量必须在函数开始地方全部申明,最近遇到了"crosses initialization of XXX"知道为什么了.就是因为有可能跳过变量的声明. 2. 代码例子 例子1: 1 #include <iostream> 2 class Test{ 3 p

goto语句

goto语句的使用: #include <iostream> using namespace std; int main() { int i = 1; number: i++; std::cout<<"*"; if(i<10) { goto number; } std::cout<<"\n 程序结束"<<endl; return 0; } 输出: ********* 程序结束 一般不用goto语句,调试困难!因为

编程题:用goto语句实现,求1+2+...+100的结果。

#include<stdio.h> void main() { int n=1,s=0; loop:if(n<=100) { s=s+n; n=n+1; goto loop; } printf("1+2+3+...+100=%d\n",s); } goto语句介绍: 运行结果: 总结:goto语句为无条件转移语句.一般不推荐使用. 编程题:用goto语句实现,求1+2+...+100的结果.,布布扣,bubuko.com

通过goto语句学习if...else、switch语句并简单优化

goto语句在C语言中实现的就是无条件跳转,第二章一上来就介绍goto语句就是要通过goto语句来更加清楚直观的了解控制结构. 我理解的goto语句其实跟switch语句有相似之处,都是进行跳转.不同的是goto语句是进行无条件的跳转,执行到这一句的时候直接就跳转了,而switch语句是要进行一个判断之后才能进行跳转.例如: 下面是用switch语句写的一个程序 1 #include <stdio.h> 2 int main(void) 3 { 4 char score; 5 scanf(&q

原来java中也有类似goto语句的标签啊--java label标签

http://blog.sina.com.cn/s/blog_6d5354cd0100xjg7.html —————————————————————————————————————————————————————————————— goto语句的危害: goto语句是在源码级上的跳转,这使其招致了不好的声誉.若一个程序总是从一个地方跳到另一个地方,还有什么办法来控制程序的流程. java中的“goto”: 虽然Java中goto语句只是java的一个保留字,没有起任何作用,但是我今天在使用con

c语言中的goto语句

goto 语句标号;实现无条件跳转 限制:goto和语句标号必须在同一个函数中,可以不在同一个循环层中. #include <stdio.h> int main(void){     int i,sum=0;     i=1; loop:if(i<=100){          sum+=i;          i++;          goto loop;      }      printf("sum=%d\n",sum);     return 0; } 结果

CMD中goto语句会中断for循环特性详解

在这个程序里面由于用到了上篇文章中所说的字符串切割,而用到了Goto强制跳转语句 但是在程序中使用的时候却发现一个错误,当把这个字符切割的代码段如果直接作为非嵌套语句执行正常 但是一旦放到for循环的复合语句中就会发现for循环只执行一次之后for循环就退出了,而且临时变量%%x的值就变成空了 换句话说就是goto跳转和目标地:labe不能同时出现在一个for语句中 例如下示例: for /f %%i in ("abc") do ( :show echo %%i & pause

C语言字符串匹配、goto语句、关机命令使用

1.程序执行修改窗口字体颜色命令: 2.程序执行修改窗口标题命令: 3.程序执行关机倒计时命令: 4.根据提示输入团队名称JYHACK TEAM 根据提示输入团队网址:http://bbs.jyhack.com 5.如果输入正确,则取消关机命令,并打开某一网页.    如果输入错误,那就等着关机吧. ps:当然对于略懂cmd命令的来说很简单,打开cmd,输入shutdown -a命令即可轻易解除. 源码如下: #include<stdio.h> //printf和scanf函数调用 #incl