为什么不GOTO声明?

时间:2013-11-04 10:54:56

标签: c# java c++ c

我正在攻读软件工程硕士学位。从大学到大学,我从我的老师和教师那里听说,他们从不在编程语言中使用GOTO语句。据此  Software Engineering By D. Sundar

  

使用goto语句会使程序非结构化并且非常有用   很难理解。

我也在MICROSOFT的书中读到了同样的第一页,它从未在编程中使用GOTO Statmement

在我看来,如果我们被告知从不使用GOTO Statement然后使用why it is the part of many common programming languages

10 个答案:

答案 0 :(得分:7)

至少对于某些编程语言(其中没有一个我是设计者,显然)就像C和C ++一样,我想它就在那里,因为它

  1. 密切模拟硬件真正可以做的事情,这是这些语言的目标。
  2. 有时候实际上有用且比更“结构化”的方法更好。
  3. goto通常被认为是好的时,最常见的例子是在C中进行嵌套错误/资源管理时。例如,参见Linux内核,这是一个使用goto的相当大且成功的C项目为了这个目的。

答案 1 :(得分:4)

你想阅读Edsger W. Dijkstra(1968年)的开创性"Go to statement considered harmful"

答案 2 :(得分:3)

java中没有goto语句。 Java keyword list指定goto关键字,但标记为" 未使用"。

答案 3 :(得分:3)

您已指示不使用goto,因为他们想教您如何编写代码。 但有时goto可能很有用。

当您想要从多级循环中立即中断时。您可以为每个步骤添加退出条件。你可以使用goto endloop 看看这个例子:(psaudo代码)

  while(cond1){
    while(cond2){
      while(cond3){
        if(want to break){
          goto endloop
        }
        do something 
        if(want to break2){
          goto endloop
        }
      }
      do something 
    }
    do something 
  }
endloop:
  do something else

没有goto它可能看起来像这样:

  while(cond1 && exitloopflag){
    while(cond2 && exitloopflag){
      while(cond3 && exitloopflag){
        if(want to break){
          exitloopflag = true;
          break;
        }
        do something 
        if(want to break2){
          exitloopflag = true;
          break;
        }
      }
      if(exitloopflag)
        break;
      do something     
    }
    if(exitloopflag)
      break;
    do something 
  }
  do something else

所以我们可以争论哪个代码可读性更好......

答案 4 :(得分:3)

goto在任何现代编程语言中的存在很大程度上是残留的,有点像人类的附录。它的功能已被条件和循环控制结构(if-then-else,for / while / loops,switch / case语句等)所取代。它在C和C ++等语言中徘徊,因为有一些边缘情况它仍然非常有用,例如突破深层嵌套循环:

for (...)
{
  for (...)
  {
     for(...)
     {
        ...
        // hit a fatal error, need to break out to outermost scope
        goto whoopsiedoodle;
     }
  }
}
whoopsiedoodle: 
...

但是,由于它可以在一个函数中分支任一方向,因此不鼓励使用它,它可以销毁通过简单检查调试代码的能力。例如,给出以下代码段:

       i = 1;
label: printf("i = %d\n", i);

i打印的值是多少?执行该打印语句的次数是多少次?在您考虑goto label;的每个实例之前,您无法知道。现在,假设代码的结构类似于以下内容:

       i = 0;
       goto label;
foo:   ...
       ...
       i = 1;
label: printf("i = %d\n", i);
       ...
       goto foo;
       ...

现在,想象一下上面代码段中每个...的几十个(甚至几个)行代码。还可以想象存在分散在其中的10或11个其他标签,其中相关的goto语句主要是随机散布的。这是在我职业生涯早期遇到的一些现实代码之后建模的。调试这样的代码的唯一方法是逐行跟踪执行,并在整个过程中计算每个goto。这段代码编写起来很糟糕(一个单行的,5000行main函数,字面上数百的单独变量,一些在文件范围声明,一些在main本地,和其他暴行),但goto的使用是一个力量放大器,只是将不良代码转变为不可维护的污泥。此代码定义“脆弱”;我们确实无法在不破坏其他东西的情况下改变它的一行。

过度使用goto也会妨碍编译器优化代码的能力。现代编译器非常智能,可以利用结构化编程技术进行有效的分支预测或展开循环以获得真正的性能提升。像上面这样的代码几乎不可能让编译器进行优化。上面代码片段的真实世界代码是什么?我们尝试在打开优化标志(gcc -O1)的情况下编译它。编译器吃掉所有可用的RAM,然后它吃掉所有可用的交换,导致内核崩溃。

我们告诉客户他们要么需要购买更快的硬件,要么允许我们从龙骨上重写整个东西。他们最终买了更快的硬件。

只要您遵守以下规则,就可以有效地使用

goto

  1. 分支前进
  2. 永远不要分支到控制结构的主体中(即,不要绕过ifforwhileswitch条件。
  3. 避免分支大部分代码。

答案 5 :(得分:2)

我想解释一下,为什么你应该非常小心地使用GOTO。

我没有说GOTO是一个糟糕的声明,这也是原因之一,为什么它仍然在C ++中实现(并且由于C的兼容性原因),在JAVA中它只保留为keyowrd。

我可以向您展示GOTO是最佳解决方案的示例(在我看来)

但由于以下原因,您应该阻止使用它:

(由我拍摄,翻译和修改,来自书籍Ohne C Zu C++

  

想象一下,你玩像Settlers of Catan这样的游戏,无论你走到哪里,任何人都有自己的游戏   规则。   没关系,你只需要学习规则,然后就可以玩它们了。

     

但是,如果他们不会教你规则,只是使用它会怎么样?你将失去游戏中的乐趣   他们非常快。

     

goto语句就像一个新的Catan规则Settler。

     

编程很难理解何时可以可靠地假设你从>顶部开始,一次执行1行,一次执行一行。

     

使用goto语句抛出窗外的假设,突然之间,“游戏!不确定。这是一个新的,不确定的规则。

答案 6 :(得分:1)

在某些语言中,它用于异常处理(例如VBA)

Java将goto作为keyword,但它什么也没做。我相信他们这样做了,你不能说出任何名字goto

但是,在某些情况下,goto可能很有用!

答案 7 :(得分:1)

Java中明确禁止使用

goto。它在其他语言中是因为它很容易实现,因为它是机器代码中的简单指令,而不是因为它是一个好主意。

BTW您可以在Java中执行类似goto的操作。看看你是否可以轻松地弄清楚这个简单的例子做了什么,如果你不能解决你自己的问题。如果你明白这是做什么以及它是如何工作的,你必须考虑到许多人会发现这一点令人困惑。

FOUND: {
    for(String s: list)
        if(s.contains(like))
             break FOUND;
    System.out.println(like + " not found");
}

答案 8 :(得分:1)

Goto语句模型机器代码;机器代码中的流控制结构非常有限,没有相应的goto就无法编写重要的机器代码程序。

原始的高级语言,例如COBOL和FORTRAN,都有Gotos,因为人们知道如何控制他们在机器上执行机器代码的流程。 C语言也创建了一个,虽然多年后,部分是因为该语言是专门创建的,易于编译为高效的机器代码 - 一些C语言结构,如增量/减量运算符,因为最初创建C的机器在其机器代码中具有这些子操作。可以说C不是高级语言,它是一个结构化的汇编语言(并且没有任何错误,它超前于时代,并且仍然非常有用)。

Dijkstra和其他人想出的是,(1)如果你有足够的更高级别的流程控制结构,并且(2)它非常容易出错,那么就没有必要使用goto。我记得读过那些代码的分析,发现goto语句出错的可能性是其他任何语句的9倍。

具有讽刺意味的是,从概念上理解声明的作用并不是最难以理解的;只是程序员使用程序员经常会使程序整体难以理解。

答案 9 :(得分:1)

我们跳跃时允许

转到

  • 超出范围,
  • 紧接着范围关闭。

所有其他情况都是无效的(跳进一个循环,跳到if-block的中间,跳进另一个函数,OMG,万圣节快乐)。

由于有几种方法可以打破范围,例如中断中断标签返回等,因此没有纯粹的<必须使用em> goto (除了一些不支持上述某些语言的早期语言,通常是 break标签)。

换句话说, goto 并没有消失(在不改变执行顺序的情况下编写程序是不可能的),我们只是通过对不同类型的执行路径使用不同的关键字来区分。 转到现在有特殊情况,它们有自己的关键字。它还使代码更容易理解。