5

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

goto 语句的使用使程序变得非结构化并且很难理解。

我也在 MICROSOFT 的书的第一页上读到了同样的内容,该书从未GOTO Statmement在编程中使用过。

在我的脑海中总是会出现一个问题,如果我们被指示永远不要使用GOTO Statementthen why it is the part of many common programming languages

4

10 回答 10

7

至少对于像 C 和 C++ 这样的一些编程语言(显然我不是其中的设计者),我想它的存在是因为它

  1. 密切模拟硬件真正可以做什么,这是这些语言的目标。
  2. 有时实际上比更“结构化”的方法更有用且更好。

什么时候被认为是好的最常见的例子是在 C 中进行嵌套错误/资源管理时。例如,参见 Linux 内核,这是一个用于此目的goto的相当大且成功的 C 项目。goto

于 2013-11-04T10:57:23.290 回答
3

您想阅读Edsger W. Dijkstra(1968 年!)

于 2013-11-04T10:57:52.667 回答
3

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

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

  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

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

于 2013-11-04T12:06:41.120 回答
3

java中没有goto语句。Java 关键字列表指定了关键字goto,但它被标记为“未使用”。

于 2013-11-04T10:58:48.897 回答
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. 避免在大段代码上进行分支。
于 2013-11-04T15:17:20.837 回答
2

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

我并不是说 GOTO 是一个糟糕的陈述,这就是为什么它仍然在 C++ 中实现的原因之一(并且由于与 C 的兼容性原因),在 JAVA 中它仅保留为关键字。

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

但是由于以下原因,您应该避免使用它:

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

想象一下,你玩像《卡坦岛定居者》这样的游戏,无论你走到哪里,每个人都有自己的规则。没关系,你只需要学习规则,然后你就可以玩它们了。

但是,如果他们不教你规则,而只是使用它呢?你会很快失去和他们一起玩游戏的乐趣。

goto 语句就像一个新的 Catan 规则定居者。

当您可以可靠地假设您从顶部开始,一次执行 1 行,向下,一次执行一行时,编程很难理解。

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

于 2013-11-04T11:16:09.443 回答
1

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

Java 有goto一个关键字,但它什么也没做。我相信他们这样做了,你不能说出任何东西goto

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

于 2013-11-04T10:57:57.097 回答
1

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

顺便说一句,您可以在 Java 中执行类似 goto 的操作。看看你是否可以很容易地弄清楚这个简单的例子做了什么,如果你不能,你就是在回答你自己的问题。如果它的作用和工作原理对您来说很明显,那么您必须考虑到很多人会觉得这令人困惑。

FOUND: {
    for(String s: list)
        if(s.contains(like))
             break FOUND;
    System.out.println(like + " not found");
}
于 2013-11-04T11:33:00.827 回答
1

当我们跳跃时,Goto是允许的

  • 超出范围,
  • 就在示波器后面紧挨着。

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

由于有几种方法可以打破范围,比如breakbreak labelreturn等,所以没有必须使用纯goto的情况(除了一些不支持上述一些的早期语言,通常是break label)。

也就是说,goto并没有消失(不改变执行顺序是不可能写出程序的),我们只是对不同类型的执行路径使用不同的关键字进行区分。Goto现在有特殊情况,它们有自己的关键字。它还使代码更易于理解。

于 2013-11-04T12:23:21.000 回答
1

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

最初的高级语言,如 COBOL 和 FORTRAN,有 Goto,因为人们知道如何通过在他们的机器上执行机器代码来控制他们的流程。C 语言也是用一种语言创建的,尽管几年后,部分原因是该语言是专门为易于编译为高效的机器代码而创建的——一些 C 语言结构,例如递增/递减运算符,之所以存在是因为最初为其创建 C 的机器在其机器代码中具有这些子操作。可以说 C 不是一种高级语言,它是一种结构化的汇编程序(这并没有错,它领先于时代,并且仍然非常有用)。

然而,Dijkstra 和其他人发现,(1) 如果您有足够的高级结构来进行流控制,则不需要 goto,并且 (2) 它非常容易出错。我记得读过一些代码分析,发现 goto 语句出错的可能性是任何其他类型语句的 9 倍。

具有讽刺意味的是,从概念上理解语句在做什么并不难。只是程序员对它的使用经常导致程序整体更难理解。

于 2013-11-04T12:10:11.980 回答