支持的版本:当前17)/ 16 / 15 / 14 / 13
开发版本:开发版
不支持的版本: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);

提交更正

如果您在文档中发现任何不正确、与您使用特定功能的经验不符或需要进一步澄清的内容,请使用此表格报告文档问题。