1

我正在查看一个只有标头的 C“库”:https ://github.com/zserge/jsmn/blob/master/jsmn.h

据我了解,这段代码将被编译到 .c 文件包含的每个目标文件中jsmn.h,浪费空间。

(文件的函数定义在里面#ifndef JSMN_HEADER,因此您可以通过定义 JSMN_HEADER 将其用作“传统”头文件。)

  • 为什么没有把它写成“传统”.c.h配对?
  • 链接器是否足够聪明,可以在目标文件之间重复功能相同的定义?我会预料到“重复符号”错误。
  • 将代码放在标头中会给 C 带来什么好处?(不是 C++。)
  • #define JSMN_HEADER如果在导入之前使用,您从哪里获得函数定义?
  • 只是jsmn.h头部是一个聪明的把戏,我可以从中学习吗?
4

1 回答 1

3

根据定义的宏,标头扩展为以下内容之一:

  1. 没有宏——函数定义(公共函数是非静态的,私有函数是)。
  2. JSMN_HEADER— 函数声明(仅适用于公共函数)。
  3. JSMN_STATICstatic函数定义(针对私有和公共函数)。

如果只有一个 TU 需要该库,您可以在 (1) 和 (3) 之间自由选择。

如果多个 TU 需要该库,则您需要 (1) 在其中一个 TU 中和 (2) 在所有其他 TU 中。那么唯一“浪费”的就是跳过(2)的函数定义的预处理器时间,但这并不重要,因为它们太小了。

在这种情况下,尝试对所有 TU 使用 (1) 会给您“重复符号”链接器错误。尝试对所有 TU 使用 (3) 会默默地复制符号,这将是一种浪费。

为什么它没有被写成“传统的” .c 和 .h 对?

为了方便分发和使用该库。

链接器是否足够聪明,可以在目标文件之间重复功能相同的定义?我会预料到“重复符号”错误。

它可能不够聪明,但没必要。

您需要定义宏,以便只有一个 TU 具有定义。

将代码放在标头中会给 C 带来什么好处?

要分发的源文件更少。

#define JSMN_HEADER如果在导入之前使用,您从哪里获得函数定义?

来自在包含标题之前未定义此宏的其他 TU。

只是jsmn.h头部是一个聪明的把戏,我可以从中学习吗?

是的。

于 2021-10-16T08:44:37.890 回答