支援的版本:目前 (17) / 16 / 15 / 14 / 13
開發版本:devel
不支援的版本:12 / 11 / 10 / 9.6

54.4. 雜項編碼慣例 #

C 標準 #

PostgreSQL 中的程式碼應該只依賴 C99 標準中可用的語言特性。這表示符合 C99 標準的編譯器必須能夠編譯 postgres,至少除了少數與平台相關的部分之外。

目前,C99 標準中包含的一些特性不允許在核心 PostgreSQL 程式碼中使用。 這目前包括可變長度陣列、交錯宣告和程式碼、// 註解、通用字元名稱。 這樣做的原因包括可移植性和歷史慣例。

如果提供了後備方案,則可以使用 C 標準的後續修訂版或編譯器特定功能。

例如,目前使用了 _Static_assert()__builtin_constant_p,即使它們分別來自 C 標準的較新修訂版和 GCC 擴充功能。 如果不可用,我們分別回退到使用 C99 相容的替代方案來執行相同的檢查,但會發出相當隱晦的訊息,並且不使用 __builtin_constant_p

類函式巨集和內聯函式 #

可以使用帶參數的巨集和 static inline 函式。 如果在編寫為巨集時存在多重求值風險,例如:

#define Max(x, y)       ((x) > (y) ? (x) : (y))

或者當巨集很長時,後者是更好的選擇。 在其他情況下,只能使用巨集,或者至少更容易。 例如,因為需要將各種型別的表達式傳遞給巨集。

當內聯函式的定義引用僅作為後端一部分可用的符號(即變數、函式)時,從前端程式碼包含該函式時可能不可見。

#ifndef FRONTEND
static inline MemoryContext
MemoryContextSwitchTo(MemoryContext context)
{
    MemoryContext old = CurrentMemoryContext;

    CurrentMemoryContext = context;
    return old;
}
#endif   /* FRONTEND */

在本例中,引用了僅在後端可用的 CurrentMemoryContext,因此使用 #ifndef FRONTEND 隱藏了該函式。 存在此規則是因為即使未使用該函式,某些編譯器也會發出對內聯函式中包含的符號的引用。

編寫訊號處理常式 #

為了適合在訊號處理常式中執行,程式碼必須非常謹慎地編寫。 根本的問題是,除非被封鎖,否則訊號處理常式可以隨時中斷程式碼。 如果訊號處理常式內的程式碼使用與外部程式碼相同的狀態,則可能會導致混亂。 例如,考慮如果訊號處理常式嘗試取得已在已中斷程式碼中持有的鎖會發生什麼。

除非有特殊安排,否則訊號處理常式中的程式碼只能呼叫異步訊號安全函式(如 POSIX 中定義),並且只能存取型別為 volatile sig_atomic_t 的變數。postgres 中的一些函式也被認為是訊號安全的,重要的是 SetLatch()

在大多數情況下,訊號處理常式應該只記錄已收到訊號,並使用閂鎖喚醒在處理常式外部執行的程式碼。 這種處理常式的一個例子如下

static void
handle_sighup(SIGNAL_ARGS)
{
    got_SIGHUP = true;
    SetLatch(MyLatch);
}

呼叫函式指標 #

為了清楚起見,如果指標是一個簡單的變數,則最好在呼叫指向的函式時顯式取消引用函式指標,例如

(*emit_log_hook) (edata);

(即使 emit_log_hook(edata) 也可以運作)。 當函式指標是結構的一部分時,可以並且通常應該省略額外的標點符號,例如

paramInfo->paramFetch(paramInfo, paramId);

提交更正

如果您在文件中發現任何不正確、與您使用特定功能的經驗不符或需要進一步澄清的內容,請使用此表單來報告文件問題。