首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言 goto 語句用法詳解:標籤跳轉、空語句與結構化編程爭議

     編輯:關於C語言

goto 基本語法


goto 標籤名;
...
標籤名: 語句;
  • goto 無條件跳轉到同一函數內的標號語句。
  • 標號由標識符 + 冒號構成,作用域為整個函數體。
  • 不能跨函數跳轉(需 setjmp/longjmp)。

經典用法示例

例 1:多條件分支統一出口


if (strlen(str) < 10) goto Label1;
else goto Label2;

Label1:
    printf("不足10字符");
    goto Label3;
Label2:
    printf("達到或超過10字符");
    goto Label3;
Label3:
    getchar(); return 0;

例 2:跳出多層循環(goto 唯一優雅方案)


while (1) {
    i++;
    printf("%d\n", i);
    if (i == 10) goto AAA;
}
AAA: printf("OK!\n");

無需設置標誌變量逐層 break,直接跳出。

例 3:跳轉到空語句(標號後無實質語句)


AAA:;  // 空語句,僅一個分號

標號必須後跟一條語句,空語句 ; 滿足語法要求。

goto 爭議與現代共識

觀點支持反對
可讀性簡化特定邏輯(錯誤處理、狀態機)導致「麵條代碼」,難以追蹤流程
結構化編程Dijkstra「Go To 有害」針對濫用現代語言提供更好替代(異常、協程)
性能編譯器優化後等價無顯著優勢
適用場景錯誤清理統一出口、狀態機、跳出多層循環一般控制流應用 if/for/while/function

最佳實踐:受限制的 goto 使用原則

  1. 僅向前跳轉(向後跳轉易造成立即循環/邏輯混亂)。
  2. 僅用於錯誤處理統一清理(Linux 內核風格):
    
    int func() {
        int *p = malloc(...);
        if (!p) goto err1;
        FILE *f = fopen(...);
        if (!f) goto err2;
        // 正常邏輯
        fclose(f);
        free(p);
        return 0;
    err2:
        free(p);
    err1:
        return -1;
    }
    
  3. 不用於一般循環/分支控制,優先用 break/continue/return/函數提取。
  4. 標號語義化命名:cleanup:、error_exit:、done:。

替代方案對比

場景goto 方案結構化替代
多層循環跳出goto label提取為函數用 return / 設置標誌變量
資源獲取失敗清理goto cleanupRAII (C++), defer (Go), try-with-resources (Java)
狀態機goto state_labelswitch 狀態表 / 函數指針表 / 協程

總結

goto 是 C 語言提供的非結構化跳轉原語。現代共識:不禁用,但嚴格限制用途。在「資源獲取失敗時的逆序清理」與「跳出深層巢狀循環」兩大場景中,goto 往往比結構化替代方案更簡潔、高效、不易出錯。除此之外,應優先使用結構化控制流構造,保持代碼可讀與可維護。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved