顾名思义,goto语句用于控制程序跳转到指定位置去执行。尽管到目前为止,我们还没有使用它写过任何程序,但不能否认在一些特殊情况下,goto语句是非常有用的。
第三章 控制流 >> 3.8 goto语句与标号
最常见的情况是:终止程序在某些深度嵌套的结构中运行,例如直接从两层或两层以上的循环中跳出。
for (...) for(...) { ... if (err) goto error; } ... error: /* clean up the mess */
如果出现错误,程序会直接跳到error:标号所在位置。由于break语句只能跳出到上一级循环,因此这种情况下使用goto语句会更方便。
而且,如果上述例子中的错误处理代码很重要,并且错误可能出现在多个地方,那使用goto语句无疑是明智的选择。
标号的命名和变量命名的形式相同,标号后面要紧跟一个冒号“:”。
标号可位于对应goto语句所在函数的内部任何位置,显然,标号的作用域便是整个函数。
再来看一个使用goto语句的例子:判定两个数组a和b中是否具有相同元素的问题。
for (i = 0; i < n; i++) for (j = 0; j < m; j++) if (a[i]== b[j]) goto found; /* didn't find any common element */ ... found: /* got one: a[i]== b[j]*/ ... ...
然后,我们来看一个实现相同功能,但不使用goto语句的例子:
found = 0; for (i = 0; i < n && !found; i++) for (j = 0; j < m && !found; j++) if (a[i]== b[j]) found = 1; if(found) /* got one: a[i-1] == b[j-1] */ ... else /* didn't find any common element */ ...
将这两个例子进行对比是为了说明:所有使用goto语句的程序代码都能改写成不带goto语句的形式,虽然可能会带来一些额外的重复测试或变量。
大多数情况下,如果在一个函数中出现过多的标号和goto语句,会导致程序难以理解和维护。所以,我们应该仅在必要的情况下,才使用goto语句和标号。