伊莉討論區

標題: 新手發問C語言Goto指令 [打印本頁]

作者: a91337a    時間: 2017-3-30 09:44 AM     標題: 新手發問C語言Goto指令

為何網路上說不能常用GOTO指令,我用了好幾次並沒有對程式判斷或著任何問題
作者: weirdococo    時間: 2017-3-30 11:29 AM

不是不能用,是因為那會破壞某一些觀念上的編程典範,想像一下,一般來說,一個subroutine有兩3個進入點,有兩個是goto過來的,那宣告進入時夾帶的參數就不見得會被傳入,subroutine的參數就變成只能當參考用的東西!
作者: johnwanz    時間: 2017-3-30 09:24 PM

GOTO是合乎規範的語法, 自然是有用的.

不過, 對於結構化程序來說, 不熟悉使用場合, 就很容易使程序呈現出不結構化的形式. 加上, 不用GOTO也能寫出很不錯的程序, 所以, 教學上, 通常都不建議使用GOTO, 或要求避免使用GOTO.

例如, 在我公司, 會要求工程師不要用; 如果有覺得需要, 必須先徵詢過主管意見. (絕大多數都是程序結構不良, 才會希望用GOTO.)

ps. 在特定條件下, GOTO其實也是很好的一種表達方式, 只是要注意使用時機.
作者: a91337a    時間: 2017-3-31 11:30 AM

johnwanz 發表於 2017-3-30 09:24 PM
GOTO是合乎規範的語法, 自然是有用的.

不過, 對於結構化程序來說, 不熟悉使用場合, 就很容易使程序呈現出 ...

經過大大的見解我已經充分了解到GOTO的意義存在^^謝謝給我這個新手解答
作者: a91337a    時間: 2017-3-31 11:33 AM

weirdococo 發表於 2017-3-30 11:29 AM
不是不能用,是因為那會破壞某一些觀念上的編程典範,想像一下,一般來說,一個subroutine有兩3個進入點, ...

看來GOTO語法也有限制性,謝謝大大給我這個新手具有參考性價值見解^^
作者: seraphnew    時間: 2017-3-31 11:01 PM

Function 中的Return 某種程度上也是一種goto。
通常建議不用,是因為邏輯判斷關係。
作者: CoNsTaRwU    時間: 2017-4-4 01:43 AM

提示: 作者被禁止或刪除 內容自動屏蔽
作者: o_g349    時間: 2017-9-13 12:05 PM

提示: 作者被禁止或刪除 內容自動屏蔽
作者: lijinf2    時間: 2018-1-9 10:26 PM

提示: 作者被禁止或刪除 內容自動屏蔽
作者: HaKkaz    時間: 2018-1-26 02:40 AM

提示: 作者被禁止或刪除 內容自動屏蔽
作者: 70413456    時間: 2018-1-29 06:03 PM

提示: 作者被禁止或刪除 內容自動屏蔽
作者: allenbody    時間: 2018-2-4 09:09 PM

提示: 作者被禁止或刪除 內容自動屏蔽
作者: 神之風想    時間: 2018-5-5 09:30 AM

謝謝大大的分享喔,小弟覺得很好喔~解決了我的問題
作者: kuolung1    時間: 2018-6-8 08:23 PM

基本上,我是不用 goto 的,我寫30年程式,但也不是完全沒用,看個人習慣
作者: jackyo04    時間: 2018-6-20 04:16 PM

我都用簡單的迴圈表達耶,用GOTO要拉來拉去很麻煩,自己用就還好,如果程式量大的話,光交接或整合就會增加別人的工作量,所以要用前先想一下吧
作者: titanping    時間: 2018-7-9 11:55 AM

提示: 作者被禁止或刪除 內容自動屏蔽
作者: affkame    時間: 2018-7-12 12:34 PM

提示: 作者被禁止或刪除 內容自動屏蔽
作者: MY0613    時間: 2018-7-12 01:49 PM

本帖最後由 MY0613 於 2018-7-12 01:53 PM 編輯

「未悟道以前,見山是山,見水是水;見道以後,見山不是山,見水不是水;最後大徹大悟以後,見山還是山,見水還是水。」

初學者就先記著這個潛規則,
程式碼看多了…
  1. if (do_something() != ERR) {
  2.     if (do_something2() != ERR) {
  3.         if (do_something3() != ERR) {
  4.             if (do_something4() != ERR) {
  5.                 ...
複製代碼
這種東西就覺得用 goto
  1. if (do_something() == ERR)  // Straight line
  2.     goto error;             // |
  3. if (do_something2() == ERR) // |
  4.     goto error;             // |
  5. if (do_something3() == ERR) // |
  6.     goto error;             // V
  7. if (do_something4() == ERR) // emphasizes normal control flow
  8.     goto error;
複製代碼
感覺就典雅很多
但是,看了一陣子…發現程式碼還是人寫的…程度不夠的人看了這段碼,為了修bug 毀了這典雅…
那還是回到原點…

總之,工具本身沒有"對錯"、"好壞"…但是用的人不同,才會顯示出差異…
參考看看。
Why do some kernel programmers use goto instead of simple while loops?
Linux Kernel source code 也存在著許多goto…但那又如何呢?


作者: cockroachrun    時間: 2018-7-13 10:22 AM

還有別的情況下也可以用goto
很多層的loop 最內層有錯發生. 外層也不要執行了. 直接用goto 離開.
example
  1. while( exp )
  2. {
  3.    while( exp2 )
  4.    {
  5.       while( exp3 )
  6.       {
  7.              ....
  8.              if( fail )
  9.                 goto exitAll;
  10.              ....
  11.   
  12.       }
  13.    }
  14. }
  15. exitAll:;
複製代碼

作者: love88131496    時間: 2018-7-13 05:43 PM

提示: 作者被禁止或刪除 內容自動屏蔽
作者: ash1326    時間: 2018-8-8 09:28 PM

指令本身是沒有問題的,但你的同事問題會很多
作者: advantise    時間: 2018-8-17 12:14 AM

沒有不能使用goto, 我認為語言的設計出來的東西都有其必要性, 很多公司都限制programmer不能使用marco, 我認為這些限制是不合理的, 而且你去看linux kernal, marco/goto 用一堆, 誰說有什麼東西不能用。
作者: advantise    時間: 2018-8-18 01:44 PM

advantise 發表於 2018-8-17 12:14 AM
沒有不能使用goto, 我認為語言的設計出來的東西都有其必要性, 很多公司都限制programmer不能使用marco, 我 ...

每個公司都不太一樣, 但是大部份的公司都認為不好維護, 這些公司有上市公司, 也有大的美商公司
作者: chevylin0802    時間: 2018-9-8 09:11 PM

其實避免使用goto是1980年代結構化程式語言教科書上的指示。當時為了強調結構化的重要性,因此提出這樣子的觀念。
但事實上,在Linux kernel卻是很常見的做法。原因出在Linux kernel採用的是物件化的觀念,由於純C的程式並沒有try catch 的語法,因此goto成為替代選項。事實上,這樣子的語法反而比結構化寫法更容易理解,同時也更不容易出錯。因為過多巢狀的if else 反而更容易出錯,尤其是程式又臭又長的情況下。試想看看,當程式裡if else裡有個五層的if else語法包覆時的情況,可讀性能好到哪去。還遠不及採用goto的方式來解決問題。
所以不要以為結構化是萬能的寫法,畢竟盡可能保持乾淨易懂的程式碼,以及盡可能減少使用巢狀式的設計,才是最重要的事情。起碼不要讓程式出現一堆{{{}}}之類的事情發生,才是最要緊的事情,因為這種巢狀結構一個不小心就更容易出錯。
作者: hunter00101    時間: 2018-9-10 09:04 AM

goto最好不要用,因為在後續除錯上,增加困難度。
作者: whyend1119    時間: 2018-9-30 01:29 PM

本帖最後由 whyend1119 於 2018-9-30 01:35 PM 編輯

樓上有很多舉出用GOTO的例子,其實都可以用try, throw和catch來完美的呈現,這也是寫程式在做error handling的標準做法,當然,這要用到C++的語法。

很多時候錯誤發生在巢狀迴圈或是判斷式中,要每個地方跳出來個別做錯誤處理,用GOTO似乎是無奈但卻很合理的選擇,正是因為這樣,才有try, throw和catch的語法出現

例如:


if (do_something() == ERR)  // Straight line
    goto error;             // |
if (do_something2() == ERR) // |
    goto error;             // |
if (do_something3() == ERR) // |
    goto error;             // V
if (do_something4() == ERR) // emphasizes normal control flow
    goto error;

就可以用下面來完成

try
{
if (do_something() == ERR)  // Straight line
    throw ERR1;             // |
if (do_something2() == ERR) // |
    throw ERR2;             // |
if (do_something3() == ERR) // |
    throw ERR3;             // V
if (do_something4() == ERR) // emphasizes normal control flow
    throw ERR4;
.......
}
carch (int error_code)
{
    // error handling here
}
作者: affkame    時間: 2018-10-3 12:50 PM

提示: 作者被禁止或刪除 內容自動屏蔽
作者: ykshieh    時間: 2018-11-28 07:57 PM

其實現在分兩派,
一派是goto很好用,另一派是不要用goto。

先說兩派主要堅持的地方,
(我是中立派的,工具好用就該用,不好用就別硬用)
不用goto的主要原因,
因為程式"不標準、不夠結構化"(只是什麼是標準...!?)
程式能力不強的人,會讓程式不知道跳到哪、讀程式碼的人不好了解。

用goto的主要原因,
因為程式該跳的時候就跳到想要的地方,
非常有效率,
不用再額外判斷許多變數後才放棄原本要執行的程式碼。

而大多數寫C語言約15年至20年以上的老手,
建議不要用goto,
是因為那個時候力吹"避免用goto,goto是不好的東西",
所以久而久之,就很少在用goto了。
(其實我覺得goto蠻像break或continue,但是又不相同)

當然,結構化的程式很好讀、好懂;
我遇過用goto會有問題(純粹是系統管理記憶體的問題),
是在用遞迴時,遞迴到一半強制跳過某個遞迴時,
系統在處理記憶體上會有問題,
但若是自己把遞迴展開成迴圈執行用goto,
則沒有記憶體的錯誤問題。

所以雖然goto可以治百病,因為可以亂跳,但是用不好也會致命。
作者: chevylin0802    時間: 2018-12-10 06:23 PM

ykshieh 發表於 2018-11-28 07:57 PM
其實現在分兩派,
一派是goto很好用,另一派是不要用goto。


這是因為系統堆疊的問題
遞迴之中再跳到另一個遞迴時
就很容易出錯
goto不在於好不好用
而是在於是否能夠避免使用過多的{}夾層
{{}}過多層的時候就不具有可讀性
所以就連Linux 原始碼
goto即使滿天飛
仍然有它一定的使用規則
通常只使用在需要判斷記憶體配置是否成功的地方
包括驅動程式物件的建立是否成功
除此之外
就很少在其他的地方看到

作者: 幻想的夢境    時間: 2019-4-15 01:41 AM

我也不愛用Goto,這樣做事超難結構化,小程式還可以,大程式丟災系,以前教授就講,Goto只有一個地方可以用,那就是這句語法可能導致整個系統或程式Crash,那這樣就得直接用Goto指向某個地方,不然crash更麻煩,不過到現在,我一次Goto都沒用到,倒是在VBA還用到一些,誰叫VBA沒有跟C一樣有continue(攤手
作者: advantise    時間: 2019-5-9 03:48 PM

指令設計出來就是有他的用處, 會不會搞混全是個人問題, 我遇過很多公司連Marco都不給使用, 因為怕別人看不懂還有容易出錯, 你覺得呢?  
作者: scottcheng    時間: 2019-5-23 05:34 PM

goto 在很多情況常被使用. 最簡單的用途在於製造同一個出口
例如你在程式裡面做了一堆 malloc , 當你要離開 function 時, 你得一個一個 free.
如果你直接 return 很容易就 memory leak. 這是很多寫c 常遇見的問題.

但是當你程式越來越大時, 或更複雜, 越容易發生這種很蠢的錯誤.
如果你要寫的很結構性, 那就要包裝好. c++ 比較有意義, c 我覺得不用特別不用goto.



作者: qwe21914    時間: 2019-11-1 12:45 PM

之前也使用過GOTO但感覺很麻煩,且怕到時Debug會暈倒~
作者: Bania    時間: 2020-1-9 11:46 AM

提示: 作者被禁止或刪除 內容自動屏蔽
作者: _ted_fu    時間: 2020-3-17 01:36 PM

應該不是說不能用,而是用的話會讓程式很難看懂(包括程式的人,別人就更不用說了),再加上這會讓debug變得更難。因此正常狀況下用function, loop, etc. 會比較好。
不過goto也不是毫無用處,像是當你想要寫一個有30個parameter的function的時候,用goto可能就是一個還不錯的做法。
作者: mark172mark172    時間: 2022-10-23 07:37 PM

工作了一段時間,是真的沒什麼看過有人使用goto,專案越大,感覺goto就會越難debug
作者: cus1943    時間: 2022-12-3 01:03 PM

如果需在多層迴圈跳出時使用goto也是一個不錯的選擇
作者: charleshwu    時間: 2023-1-26 10:36 PM

Goto 不是不能用,而是不容易用的好,當然在特定的情況下它是非常有用的,所以它並沒有被廢除,但除了那幾種特定的用法之外,用了 Goto 會讓程式難以被看懂與維護。所以盡量不要用它。




歡迎光臨 伊莉討論區 (http://a402.file-static.com/) Powered by Discuz!