# 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);