天天看點

goto在c語言中的作用,為什麼在C語言中,goto這麼不受待見?

原标題:為什麼在C語言中,goto這麼不受待見?

什麼是goto語句

goto語句被稱為C語言中的跳轉語句。用于無條件跳轉到其他标簽。它将控制權轉移到程式的其他部分。

goto語句一般很少使用,因為它使程式的可讀性和複雜性變得更差。

文法

goto label;

goto語句示例

讓我們來看一個簡單的例子,示範如何使用C語言中的goto語句。

打開Visual Studio建立一個名稱為:goto的工程,并在這個工程中建立一個源檔案:goto-statment.c,其代碼如下所示 -

#include void main {int age;

gotolabel:printf("You are not eligible to vote!");

printf("Enter you age:");scanf("%d", &age);if (age < 18) {goto gotolabel;}else {printf("You are eligible to vote!");}

}

執行上面代碼,得到以下結果

You are not eligible to vote!Enter you age:12You are not eligible to vote!Enter you age:18You are eligible to vote!

為什麼它這麼不受待見?

二十幾年前,當計算機程式設計尚處于起步階段時,程式流程是由“GOTO”語句來控制。該類語句允許程式員對目前代碼行斷行,而直接進入另一個不同的代碼段。清單1為簡單的示例。

goto在c語言中的作用,為什麼在C語言中,goto這麼不受待見?

使用GOTO語句

程式設計語言終究開始引入了函數的概念,即允許程式對代碼進行斷行。如果已經完成,不再使用goto語句來表示代碼的斷行。函數調用後,函數将回到下一條指令。清單2為示例。這一做法改善了程式結構,提高了可讀性。自此,這被視為編寫程式的正确方法。隻要看到或想到goto語句,就會讓軟體工程師退縮,産生本能 的厭惡。其中一個主要的原因是,一個遍布goto語句的程式會讓讓人很難抓住重心,不便于對程式的了解和維護。

goto在c語言中的作用,為什麼在C語言中,goto這麼不受待見?

用函數控制流程

而wikipedia上的解釋就是,GOTO語句一直是批評和争論的目标,主要的負面影響是使用GOTO語句使程式的可讀性變差,甚至成為不可維護的「面條代碼」。随着結構化程式設計在二十世紀六十年代到七十年代變得越來越流行,許多計算機科學家得出結論,即程式應當總是使用被稱為「結構化」控制流程的指令,如迴圈以及if-then-else語句來替代GOTO。

甚至在今天,許多程式風格編碼标準禁止使用GOTO語句。為GOTO語句辯護的人認為,加以限制地使用GOTO語句不會導緻低品質的代碼,并且聲稱在許多程式設計語言中,一些任務如果不使用一條或多條GOTO語句是無法被直接實作的。如有限狀态自動機的實作、跳出嵌套循環以及異常處理。

大概最著名的對于GOTO的批評是艾茲格·迪傑斯特拉(Edsger Wybe Dijkstra)在1968年的一篇名稱為《GOTO陳述有害論》的論文。[2]迪傑斯特拉認為不加限制地使用GOTO語句應當從進階語言中廢止,因為它使分析和驗證程式正确性(特别是涉及循環)的任務變得複雜。

另外一種觀點出現在高德納的Structured Programming with go to Statements [3]中,文章分析了許多常見程式設計任務,然後發現其中的一些使用GOTO将得到最理想的結構。

這些批評在一些程式設計語言的設計上起到了效果。雖然Ada語言的設計者在二十世紀七十年代晚期意識到了對于GOTO的批評,這條語句仍舊被包含進去,主要是用來支援自動生成那些goto語句必不可少的代碼。

[4]但是,作為goto語句目的地的标簽必須使用雙尖括号括起來(如:<>),而這個文法在其他語言中都不被使用。這使得檢查程式中goto目的地的存在變得容易。goto語句本身使用簡單的形式goto Start_Again;.

另外,有許多不同的語言構成可以看作是goto的變形:

限制的GOTO

許多語言,如C語言和Java,提供了相關的控制流語句,如break和continue,它們都是有效地被限制的goto語句。它們的作用是無條件跳轉,但是隻能夠跳到循環塊結束的位置——繼續進入下一循環(continue)或者結束循環(break)

switch/case結構

C語言、C++和Java中的switch語句高效地實作了一個多路goto,跳轉目标由表達式的值來選擇。

這也導緻了我們沒有不得不使用goto的理由。

針對這些,導緻目前goto的使用情況是這樣的:

goto語句的結果:在C/C++等進階程式設計語言中保留了goto語句,但被建議不用或少用。在一些更新的進階程式設計語言,如Java不提供goto語句,它雖然指定goto作為關鍵字,但不支援它的使 用,使程式簡潔易讀;盡管如此後來的c#還是支援goto語句的,goto語句一個好處就是可以保證程式存在唯一的出口,避免了過于龐大的if嵌套。

另一方面,goto語句隻是不提倡,當然不是禁用,那麼在什麼情況下可以使用goto語句呢?

可以考慮使用goto的情形:

從多重循環中直接跳出 ;

出錯時清除資源;

可增加程式的清晰度的情況。

不加限制地使用goto:破壞了清晰的程式結構,使程式的可讀性變差,甚至成為不可維護的"面條代碼"。經常帶來錯誤或隐患,比如它可能跳過了某些對象的構造、變量的初始化、重要的計算等語句。

下列關于使用goto語句的原則可以供讀者參考。

1) 使用goto語句隻能goto到同一函數内,而不能從一個函數裡goto到另外一個函數裡。

2) 使用goto語句在同一函數内進行goto時,goto的起點應是函數内一段小功能的結束處,goto的目的label處應是函數内另外一段小功能的開始處。

3) 不能從一段複雜的執行狀态中的位置goto到另外一個位置,比如,從多重嵌套的循環判斷中跳出去就是不允許的。

4)應該避免像兩個方向跳轉。這樣最容易導緻"面條代碼"。

閱讀過linux核心代碼的同學應該注意到,linux核心代碼裡面其實有不少地方用了goto語句,但是你會發現,它的使用非常謹慎,基本都遵循上面提到的幾個原則。

﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌

免責聲明:内容整理自網絡,版權歸原作者所有,如涉及作品版權問題,請及時與我們聯系,謝謝!

你和大牛工程師到底差了啥?

加入技術交流群,與高手面對面

添加發燒友小助手入群傳回搜狐,檢視更多

責任編輯: