C 中的函数前缀与“函数结构”

Rec*_*ion 8 c struct function prefix

我正在尝试找出 C(11) 中的最佳实践。因为没有命名空间,我可以想到两种避免名称冲突的方法:

a.) 函数前缀

void kernel_init(void) { ... }
int kernel_start(void* foo) { ... }
Run Code Online (Sandbox Code Playgroud)

b.) “函数结构”

struct kernel {
    void (*init)(void);
    int (*start)(void* foo);
} kernel;
Run Code Online (Sandbox Code Playgroud)

我不是在问哪种方法更漂亮,因为那是相当主观的。我要问的是,除了代码风格之外,这两种方法有什么明显的缺点吗?这包括一开始不相关但随着代码库增长而成为更大问题的小事情。

unw*_*ind 8

有趣的是,我以前从未想过这个解决方案。

第一个当然是标准的,我敢打赌你会在绝大多数 C 项目中找到它[*]。

第二个理论上需要内存,因为您实际上是在声明一个充满函数指针的数据对象。您当然还需要初始化kernel变量,即具有以下内容:

...
} kernel = {
  .init = kernel_init,
  .start = kernel_start,
};
Run Code Online (Sandbox Code Playgroud)

但是,哦,您又使用了带前缀的函数。要删除那些需要的功能必须是static,我的猜测是可能的,如果您添加externstruct在声明kernel.h

所以一个更完整的例子可能是:

// kernel.h (public header)
typedef struct kernel_api {
  void (*init)(void);
  int (*start)(void* foo);
} kernel_api;

extern const kernel_api kernel;

// in kernel.c
static void init(void)
{
  ...
}

static int start(void *foo)
{
  ..
}

const kernel_api kernel = {
  .init = init,
  .start = start,
};
Run Code Online (Sandbox Code Playgroud)

这可能有效,但我还没有尝试过。

最后,拥有显式数据意味着需要一个足够聪明的编译器来优化它们并进行更直接的调用,但我还没有尝试过,依赖它有点冒险。有趣的。

[*] 我想我只是在统计上声称我已经看到(或想到)了世界上绝大多数的 C 项目,但这当然不是真的。:)