_Noreturn / [ [noreturn] ](不回傳指定)
/ NOH-ree-turn /
大多數函式被呼叫後最終會回到呼叫者。但有少數永遠不會:abort() 殺掉程式、exit() 終止它、永遠迴圈的函式、或總是呼叫另一個不回傳函式的函式。告訴編譯器某函式永不回傳,能讓它產生更好的程式碼與更好的警告。這個宣告正是 _Noreturn(C11)與 C23 屬性拼法所表達的。
你在函式的宣告中標註它:_Noreturn void die(const char *msg);(或較友善地用 <stdnoreturn.h> 的 noreturn),而在 C23 你用雙中括號寫成的屬性形式,置於函式前。這個承諾是:控制流永遠不會從此函式回到呼叫者。因為編譯器現在知道 die() 呼叫之後的程式碼不可達,它可以省略某條以 die() 結尾路徑上「缺少 return」的警告、移除死碼、並避免設置一般的回傳。
它對致命錯誤輔助函式、斷言失敗、以及 longjmp 風格的跳脫很有用,讓意圖明確並消除假警告。尖銳的提醒:這是「承諾」而非檢查——若一個標了 _Noreturn 的函式實際上「真的」回傳(例如執行到結尾掉出去),行為就是未定義的,而最佳化器可能早已刪除了原本之後會執行的程式碼。另請注意 C23 已棄用 _Noreturn 關鍵字形式,改採屬性。
#include <stdlib.h> [ [noreturn]] void die(const char *msg) { // C23 屬性形式 fputs(msg, stderr); exit(1); // 控制永不回傳 } int f(int x) { if (x < 0) die("bad"); return x; } // 不會有缺少 return 的警告
把 die 標成不回傳,讓編譯器把 die() 呼叫之後的程式碼視為不可達,並略過缺少 return 的警告。
它是承諾,而非編譯器會檢查的保證:若 _Noreturn 函式真的回傳,行為就是未定義的——且 C23 已棄用 _Noreturn 關鍵字,改採屬性拼法。