且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

《编写高质量代码:改善c程序代码的125个建议》——建议25:尽量避免使用goto语句

更新时间:2022-04-08 23:51:43

本节书摘来自华章计算机《编写高质量代码:改善c程序代码的125个建议》一书中的第3章,建议25,作者:马 伟 更多章节内容可以访问云栖社区“华章计算机”公众号查看。

建议25:尽量避免使用goto语句

自从提倡结构化程序设计以来,goto 语句就成为业界争议最大的语句。不论各家对goto 语句的意见是好是坏,总结前人的经验,还是应该尽量避免在程序中使用goto语句,其原因主要有以下两方面。
首先,由于goto 语句可以灵活跳转,如果不加限制,它的确会破坏结构化设计风格,如下面的示例代码所示:

A: 
   /*处理代码*/ 
   goto B; 
   /*处理代码*/ 
   goto C; 
B:  
   /*处理代码*/ 
   goto A; 
   /*处理代码*/ 
   goto C; 
C: 
   /*处理代码*/ 
   goto A; 
   /*处理代码*/ 
   goto B;

很显然,上面的示例代码已经能够说明问题了,随着标签数量增多,将给代码的可读性、可调试性与可维护性带来一场灾难。
其次,若不加限制地使用goto语句,该语句可能跳过变量的初始化、重要的计算等语句,从而给程序带来灾难性的错误与潜在的安全隐患,如下面的示例代码所示:

char *p = NULL;
   /*处理代码*/

   goto state;

   /*变量sum被goto 跳过*/
   int sum = 0; 
   /*指针p被goto 跳过,没有分配内存*/
   p = (char *)malloc(40 * sizeof(char));
   if (p == NULL) 
   {    
           /*处理代码*/
   }
   /*处理代码*/

state:

   /*使用p指向的内存里的值的代码*/
   /*使用变量num*/

如上面代码所示,如果编译器不能发现此类错误,则每用一次goto 语句都可能导致程序出现灾难性的错误与潜在的安全隐患。
当然,如果遇到下列情况,goto 语句还是有其自身优势的。

for(...) 
    { 
            for(...) 
            { 
                    for(...) 
                    { 
                            /*使用goto语句跳出循环,执行其他的语句*/ 
                            goto A;
                    } 
            } 
    } 
A:
    /*处理代码*/

在上面的代码中,如果使用break语句,则只能跳出单层的循环;如果使用return语句,则会跳出整个函数,无法继续执行其他的代码。因此,这里可以使用goto语句。其实,如果陷入很深层次的循环中想要跳出最外层的循环,用 goto 直接跳出比用 break 一层循环一层循环跳出要好得多。