# 54.4.杂项编码约定

# C标准

PostgreSQL中的代码应该只依赖C99标准中可用的语言功能。这意味着一个合格的C99编译器必须能够编译Postgre,至少除了一些依赖于平台的部分之外。

C99标准中包含的一些功能目前不允许在核心PostgreSQL代码中使用。目前包括可变长度数组、混合声明和代码,//注释,通用字符名。原因包括可移植性和历史实践。

如果提供了回退,则可以使用C标准更高版本的功能或编译器特定的功能。

例如_静态断言()__内置常数目前正在使用,尽管它们分别来自C标准和GCC扩展的较新版本。如果不可用,我们将分别使用C99兼容的替代品,该替代品执行相同的检查,但会发出相当隐秘的消息,并且不会使用__内置常数.

# 类似宏和内联函数的函数

两者都有,带参数的宏和内联函数函数,可以使用。如果以宏形式编写时存在多个评估危害,则后者更可取,例如

#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前端。之所以存在此规则,是因为即使未使用内联函数,某些编译器也会发出对内联函数中包含的符号的引用。

# 编写信号处理器

为了适合在信号处理器内部运行,必须非常仔细地编写代码。基本问题是,除非被阻止,否则信号处理器可以随时中断代码。如果信号处理器内部的代码使用与外部代码相同的状态,则可能会出现混乱。举个例子,如果一个信号处理程序试图获取一个已经被保存在中断代码中的锁,那么会发生什么。

禁止信号处理程序中的特殊安排代码只能调用异步信号安全函数(定义见POSIX)并访问类型为挥发性sig_原子.中的一些功能博士后重要的是,它们也被认为是信号安全的SetLatch().

在大多数情况下,信号处理程序只需注意信号已经到达,并使用闩锁唤醒在处理程序外部运行的代码。以下是此类处理程序的一个示例:

static void
handle_sighup(SIGNAL_ARGS)
{
    int         save_errno = errno;

    got_SIGHUP = true;
    SetLatch(MyLatch);

    errno = save_errno;
}

呃不因为SetLatch()可能会改变。如果没有这样做,当前正在检查的代码将被中断呃不可能会看到错误的值。

# 调用函数指针

为清楚起见,如果指针是简单变量,则在调用指向函数时,最好显式取消引用函数指针,例如:

(*emit_log_hook) (edata);

(尽管发射日志挂钩(edata)也可以)。如果函数指针是结构的一部分,那么额外的标点符号可以而且通常应该省略,例如:

paramInfo->paramFetch(paramInfo, paramId);