顯示廣告
隱藏 ✕
※ 本文為 ChiChi7.bbs. 轉寄自 ptt.cc 更新時間: 2017-10-13 01:00:36
看板 Gossiping
作者 grapherd (NULL)
標題 Re: [問卦] C語言沒人用goto?
時間 Thu Oct 12 06:56:41 2017


※ 引述《bencert (根本ㄏㄏ)》之銘言:
: 小弟我剛剛想起來
: C語言有種用法是goto
: 但是上程式設計的課老師也跳過不教
: 我看也沒人用過goto
: 有沒有C語言GOTO的八卦?
: -----
: Sent from JPTT on my Samsung SM-G930F.

八卦是,ptt 的程式碼裡面也有使用 goto.

在 c99 spec 裡面,goto 是定義在 6.8.6 Jump Statements
其中的 6.8.6.1 The goto statement. 作用就是提供一個無條件
跳躍的功能. Spec 裡面給的範例是這個:

    /* ... */
    goto first_time;
    for (;;) {
        // determine next operation
        /* ... */
        if (need to reinitialize) {
            // reinitialize-only code
            /* ... */
        first_time:
            // general initialization code
            continue;
        }
        // handle other operations
        /* ... */
    }

基本上這樣的形式,還是能夠做簡化的,只要把 first_time label
下面的 initialization code 做成一個 function 去 call,就不用
用到 goto label 了。


至於會使用到 goto 的一些理由,在要求結構化程式碼,以及編譯器
優化隨著技術進步的關係,也越來越站不住腳了。

至於為什麼台灣都有種無腦不使用 goto 的教條呢?因為當老師的
只會舉一些鳥蛋的例子啊:

    int main() {
        int i = 0;

    loop:
        printf("%d\n", i++);
        if (i < 10)
            goto loop;
    }

然後就沒了。

  然後就沒了。

    然後就沒了。



目前比較大的 C 語言專案中用到 goto,幾乎都是在做 exception handling 的部分,
因為 C 語言的特性,出錯了的時候,很多動態配置的記憶體會需要回收掉,
要不然會造成 memory leak。這時候 goto 就變得很方便。例如說 CPython
的這段程式碼:


    static void
    TaskObj_finalize(TaskObj *task)
    {
        /* ... */
        if (task->task_state != STATE_PENDING ||
            !task->task_log_destroy_pending) {
            goto done;
        }

        /* ... */
        context = PyDict_New();
        if (context == NULL) {
            goto finally;
        }

        message = PyUnicode_FromString("Task was destroyed...");
        if (message == NULL) {
            goto finally;
        }

        /* ... */
    finally:
        Py_XDECREF(context);
        Py_XDECREF(message);

        /* Restore the saved exception. */
        PyErr_Restore(error_type, error_value, error_traceback);

    done:
        FutureObj_finalize((FutureObj*)task);
    }

    https://github.com/python/cpython/blob/master/Modules/_asynciomodule.c#L1711
cpython/_asynciomodule.c at master ·  python/cpython ·  GitHub
[圖]
cpython - The Python programming language ...

 

這邊就能很明顯看出 goto 的作用啦,第一個 goto done,因為還沒有
allocate context 或是 message,所以不需要去做善後的工作,如果這時候
觸發這個 goto 的話,就直接到底就好。

但是如果遇到 context 或是 message allocate 失敗的話,因為已經有
allocate 一些資源,就必須要跳到 finally 去把這些資源給清空以及還原。

在 Linux kernel 裡面也有許多需要做 exception handling 的部分,
因此也大量的使用了 goto, 但不太會有教科書上那種錯誤範例的使用方式
在裡面就是了。



最後,pttbbs 本身也有用啊 XDDD

https://github.com/ptt/pttbbs/blob/master/mbbsd/brc.c#L689

 
https://github.com/ptt/pttbbs/blob/master/mbbsd/brc.c#L704

 
https://github.com/ptt/pttbbs/blob/master/mbbsd/edit.c#L2250

 
https://github.com/ptt/pttbbs/blob/master/mbbsd/edit.c#L1848

 
https://github.com/ptt/pttbbs/search?q=goto
Search ·  goto ·  GitHub
[圖]
pttbbs - PTT BBS source code ...

 

更多 goto,請參考 wikipedia:

https://en.wikipedia.org/wiki/Goto#Common_usage_patterns_of_Goto
Goto - Wikipedia GoTo (goto, GOTO, GO TO or other case combinations, depending on the programming language) is function call normally returns control. The jumped-to locations are usually identified using labels, though some languages use line numbers. At the machine code level, a goto is a form of branch or jump sta ...
 

--
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 140.113.63.78
※ 文章代碼(AID): #1Ptg6po0 (Gossiping)
※ 文章網址: https://www.ptt.cc/bbs/Gossiping/M.1507762611.A.C80.html
※ 編輯: grapherd (140.113.63.78), 10/12/2017 06:58:05
sppmg: 認真文給推1F 10/12 07:02
pzyc79: 語義不明 就不要怪人們亂用2F 10/12 07:02
amethystboy: 認真給推 我都goto 來goto去 只有自己懂3F 10/12 07:09
soga0806 
soga0806: 認真給推4F 10/12 07:14
knetlalala: push5F 10/12 07:18
FlyinwindX: 認真給推!6F 10/12 07:41
PONANZA: 快推 不然人家會以為我看不懂7F 10/12 07:44
moonshade: 通常是用在early exit 之類的,但是因為有很多亂用的8F 10/12 07:55
moonshade: 人所以教學上會先教不要用,你如果看過一些光怪陸離
moonshade: C/C++ 使用方法就會覺得教不要用是對的
bab7171: linux kernel用超多11F 10/12 07:56
jodojeda: 我不用goto這種爛指令 我都用comefrom12F 10/12 08:05
louiseeg: 應該要有一本書叫 the art of goto13F 10/12 08:11
anshley: 宅氣衝天14F 10/12 08:11
WWWSENTYOU: 快推 不然人家會以為我看不懂15F 10/12 08:18
wanzi0601: 我認為goto解讀會變差..不太用16F 10/12 08:18
asd97190: 推17F 10/12 08:29
lpoijk: 不用goto是哪些人...?18F 10/12 08:37
Chiustin: 深入淺出goto19F 10/12 08:39
assassinzero: 113不簡單20F 10/12 08:39
weareworld: 把exception包成函式不就好了?21F 10/12 08:41
OGC218: 文組如我…看不懂22F 10/12 08:48
greed3819: 我們老師跟我說這樣會破壞程式結構叫我們不要使用,就23F 10/12 08:52
greed3819: 連課本裡也寫不建議使用?
xhung: 推 認真文 goto在err_handling真的方便XD25F 10/12 09:04
a2470abc: 優文推 goto實務好像都拿來做例外的處理26F 10/12 09:14
mikapauli: 因為例外處理本身就是一件破壞程式結構的事情27F 10/12 09:19
loloman: 就科技廠的機台可以處理run time error hang up狀況28F 10/12 09:20
a5245242003: 推29F 10/12 09:25
Huffman: 推30F 10/12 09:32
cy4v: 推31F 10/12 09:48
musie: 沒有delimited continuation的低階語言才會要用goto32F 10/12 09:51
buffalobill: 動態配製那邊通常會用do{}while(0);加上break;吧33F 10/12 09:52
dou0228: 不是,通常是最後要回收 memory 或其他 resource34F 10/12 09:54
dou0228: goo.gl/p3v23T
cks908147: 快推,不然人家以為我不懂36F 10/12 10:38
casd82: 長知識推37F 10/12 10:49
lozupomelo: U文38F 10/12 10:51
thomaschion: 我知道goto Hawaii39F 10/12 11:29
aadsl: 完全看不懂 哀 難怪我只能領低薪40F 10/12 11:30
george40516: 我用goto只會把自己搞混 看來是功力不足@@41F 10/12 12:08
kersihi: 完全看不懂 哀 難怪我只能領低薪42F 10/12 12:22
AirLee: 樓上我也是43F 10/12 13:06
zzzz8931: 問高納德教授啦44F 10/12 13:25
greg870601: 沒辦法R C++比較強,goto基本上沒用了45F 10/12 13:34
dou0228: C++ 能比 goto 難懂的東西多得是46F 10/12 14:30
vvrr: 用do{}while(0)+break,跳出do之後還是要跑過接下來的每一行47F 10/12 15:39
vvrr: goto可以根據不同的錯誤,跳過某些行。當然也可以在break
vvrr: 前設好錯誤碼,再根據錯誤碼寫if/else,但這樣反而很亂..
hinajian: 嗯,同意50F 10/12 15:42

--
※ 看板: Gossiping 文章推薦值: 3 目前人氣: 0 累積人氣: 2006 
分享網址: 複製 已複製
( ̄︶ ̄)b ggcow, klin1, goest101 說讚!
1樓 時間: 2017-10-13 10:51:22 (台灣)
  10-13 10:51 TW
沒有人說不能用goto。如果goto不能用,在設計C語言時就不會放進去了。只是說goto用太多會讓人在閱讀code上很不方便。
2樓 時間: 2017-10-14 01:18:12 (台灣)
  10-14 01:18 TW
還好組合語言只有jmp,沒有goto...
r)回覆 e)編輯 d)刪除 M)收藏 ^x)轉錄 同主題: =)首篇 [)上篇 ])下篇