2024 年 9 月 26 日: PostgreSQL 17 发布!
支持的版本:当前 (17) / 16 / 15 / 14 / 13 / 12
开发版本:devel
不支持的版本: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);

提交更正

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