首頁  >  文章  >  系統教程  >  為什麼Linux核心大量使用goto,而很多書籍卻不提倡使用?

為什麼Linux核心大量使用goto,而很多書籍卻不提倡使用?

PHPz
PHPz轉載
2024-02-05 13:25:271222瀏覽

關於C語言中的goto語句,存在著許多爭議,許多書籍建議要「謹慎使用,甚至避免使用」。但是,在Linux之父Linus的實踐中,他在Linux中廣泛使用了goto語句,這也啟示了我們可以合理地使用這個特性。

正因為有爭議,我們有必要學會使用goto語句。下面來看一些goto語句的基本語法和範例:

一、goto的基本語法

goto語句由兩個部分組成:關鍵字goto和標籤名。標籤的命名規則與變數的命名規則相同。範例:

goto label;

要讓這句語句正常運作,函數也必須包含另一個標為label的語句,該語句以標籤名後緊跟著一個冒號開始,如:

label:printf(“goto here.\n”);

二、goto的例子

左右滑動查看全部程式碼>>>

/*
编译环境:mingw32  gcc6.3.0
*/
#include 
#include 

/* goto测试 */
void TestGoto(void)
{
    int i;
 
    while (1)
    {
 for (i = 0; i if (i > 6)
     {
  goto label;
     }
     printf("%s : i = %d\n", __FUNCTION__, i);
 }
    }
 label:
     printf("test goto end!");
}
 
int main(void)
{
    TestGoto();
}

運行結果:

為什麼Linux核心大量使用goto,而很多書籍卻不提倡使用?

從運行結果我們明顯可以知道goto用法,可以跳出多重循環,程式執行過程中遇到goto語句就可以跳到label繼續執行。

值得注意的一點是:goto語句與其跳躍的標籤處必須在同一個函數內。

三、goto與break、continue的差別?

同樣是跳轉語句,goto語句與break、continue語句有什麼差別呢?

實際上,break和continue是goto的特殊形式。使用break與continue的好處是:其名稱已經表明他們的用法。

下面透過程式碼實例看一下break與continue的用法:

1、break測試函數

#使用上面的測試程序,建立一個測試break語句的函數void TestBreak(void);,如:

左右滑動查看全部程式碼>>>

/* break测试 */
void TestBreak(void)
{
    int i;
 
    while (1)
    {
 for (i = 0; i if (i > 6)
     {
         break; /* 第一个break:跳出for循环 */
     }
     printf("%s : i = %d\n", __FUNCTION__, i);
 }
 printf("Now i = %d\n", i);
 break;     /* 第一个break:跳出while循环 */
    }
    printf("test break end!");
}

運行結果:

為什麼Linux核心大量使用goto,而很多書籍卻不提倡使用?

從運行結果我們明顯可以知道,break可以退出目前迴圈。

在本範例中,第一個break語句退出目前的for迴圈,第二個break語句退出目前的while迴圈。可見,一個break可退出一層迴圈。

所以,根據break與goto的特色知道,如果是跳出很多層循環,使用goto會方便些。

2、continue測試函數

同樣的,建立一個測試continue語句的函數void TestContinue(void);,如:

左右滑動查看全部程式碼>>>

/* continue测试 */
void TestContinue(void)
{
    int i;
 
    for (i = 0; i if (i > 6)
 {
     printf("i = %d, continue next loop\n", i);
     continue; /* continue:结束本次循环(而不是终止这一层循环)继续进入下一次循环 */
 }
 printf("%s : i = %d\n", __FUNCTION__, i);
    }
    printf("test break end!");
}

運行結果:

為什麼Linux核心大量使用goto,而很多書籍卻不提倡使用?

從運行結果我們明顯可以知道,continue可以結束本次循環(而不是整個循環)而進入下一個循環(i所代表的就是循環的次數)。

四、支持与反对goto的理由是什么?

1、不提倡使用goto

不提倡使用goto的占比应该比较多,不提倡的原因主要是:很容易把逻辑弄乱且难以理解。

2、使用goto的理由

这一部分人认为goto可以用在以下两种情况比较方便:

(1)跳出多层循环。

这个例子就类似于我们上面的goto测试程序。

(2)异常处理。

一个函数的执行过程可能会产生很多种情况异常情况。下面有几种处理方式,以代码为例:

方法一:做出判断后,如果条件出错,直接return。

*左右滑动查看全部代码>>>*

int mystrlen(char *str)
{
   int count = 0;
   if (str == NULL)
   {
      return-1;
   }

   if (*str == 0)
   {
      return0;
   }

   while(*str != 0 )
   {
      count++;
      str++;
   }
   return count;
}

方法二:先设置一个变量,对变量赋值,只有一个return。

*左右滑动查看全部代码>>>*

int mystrlen(char *str)
{
   int ret;
   if (str == NULL)
   {
      ret = -1;
   }
   elseif (*str == 0)
   {
      ret = 0;
   }
   else
   {
      ret = 0;
      while(*str != 0 )
      {
         ret++;
         str++;
      }
   }
   return ret;
}

方法三:使用goto语句。

*左右滑动查看全部代码>>>*

int mystrlen(char *str)
{
   int ret;
   if (str == NULL)
   {
      ret = -1;
      goto _RET;
   }

   if (*str == 0)
   {
      ret = 0;
      goto _RET;
   }
       
   while(*str !=0 )
   {
      ret++;
      str++;
   }

_RET:
   return ret;
}

其中,方法三就是很多人都提倡的方式。统一用goto err跳转是最方便且效率最高的,从反汇编语句条数可以看出指令用的最少,消耗的寄存器也最少,效率无疑是最高的。

并且,使用goto可以使程序变得更加可扩展。当程序需要在错误处理时释放资源时,统一到goto处理最方便。这也是为什么很多大型项目,开源项目,包括Linux,都会大量的出现goto来处理错误!

以上是為什麼Linux核心大量使用goto,而很多書籍卻不提倡使用?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:lxlinux.net。如有侵權,請聯絡admin@php.cn刪除