c - 如何在翻译单元之间共享一组内部功能而不需要外部链接?

标签 c static external static-libraries linkage

假设您正在编写一个库,并且您有一堆专为自己编写的实用函数。当然,您不希望这些函数具有外部链接,这样它们就不会被您的库用户混淆(主要是因为您不会告诉外界它们的存在)

另一方面,这些函数可能在不同的翻译单元中使用,因此您希望它们在内部共享。

举个例子吧。您有一个可以执行某些操作的库,并且在不同的源文件中,您可能需要 copy_filecreate_directory,因此您可以将它们实现为实用函数。

为了确保您的库的用户不会因为具有相同名称的函数而意外得到链接错误,我可以想到以下解决方案:

  • 糟糕的方法:将函数复制粘贴到使用它们的每个文件中,并在其声明中添加 static
  • 这不是一个好方法:将它们编写为宏。我喜欢宏,但这不适合这里。
  • 给它们起一个如此奇怪的名字,这样用户产生相同名字的机会就足够小了。这可能有效,但它使使用它们的代码变得非常难看。
  • 我目前所做的:将它们作为static函数写入内部utils.h文件中,并将该文件包含在源文件中。

现在最后一个选项几乎可以正常工作,只是它有一个问题:如果您不使用其中一个函数,至少您会收到有关它的警告(表示函数声明为静态但从未使用过)。你可以说我疯了,但我的代码没有警告。

我采取的做法是这样的:

utils.h:

...
#ifdef USE_COPY_FILE
static int copy_file(/* args */)
{...}
#endif

#ifdef USE_CREATE_DIR
static int create_dir(/* args */)
{...}
#endif
...

文件1.c:

#define USE_COPY_FILE
#define USE_CREATE_DIR
#include "utils.h"

/* use both functions */

文件2.c

#define USE_COPY_FILE
#include "utils.h

/* use only copy_file */

然而,这种方法的问题是,随着更多实用程序的引入,它开始变得丑陋。想象一下,如果你有 10 个这样的函数,那么在包含之前你需要有 7~8 行定义,如果你需要 7~8 个这样的函数!

当然,另一种方法是使用排除函数的DONT_USE_*类型的宏,但话又说回来,您需要为使用很少这些实用函数的文件进行大量定义。

无论哪种方式,它看起来都不优雅。

我的问题是,如何拥有自己库内部的函数、供多个翻译单元使用,并避免外部链接?

最佳答案

将函数标记为static inline而不是static将使警告消失。它不会对当前解决方案的代码膨胀产生任何影响——您至少将该函数的一个副本放入每个使用它的 TU 中,情况仍然如此。奥利在评论中表示,链接器可能足够聪明,可以合并它们。我并不是说它不是,但不要指望它:-)

通过鼓励编译器实际内联调用函数,以便每个 TU 获得多个副本,它可能甚至会使膨胀变得更糟。但这不太可能,GCC 大多数情况下都会忽略 inline 关键字的这一方面。它根据自己的规则内联或不内联调用。

这基本上是您在可移植方面可以做的最好的事情。标准 C 中无法定义一个符号,该符号位于某些 TU(您的)的 POV 外部,但不来自其他人(您的用户)的 POV。标准 C 并不真正关心库是什么,或者 TU 可能分几个步骤链接的事实,或者静态链接和动态链接之间的差异。因此,如果您希望这些函数在您的 TU 之间实际共享,而没有任何可能干扰库用户的外部符号,那么您需要执行一些特定于 GCC 和/或您的静态库或 dll 格式的操作,以删除一次符号该库已构建,但在用户链接它之前。

关于c - 如何在翻译单元之间共享一组内部功能而不需要外部链接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10734735/

相关文章:

javascript - 为所有内容添加一个外部 js 文件?

external - 找出外部命令的可运行性

c++ - 指向不同类型的指针

char * 函数在 C 中无法正确显示

c - 使用带有多个参数的 execlp 运行 linux 命令作为 c 中的字符串

java - 如果 ArrayList 是实例变量,它是否会在 Java 中自动声明为静态?

static - API : Top 100 twitter users in a country (rank by followers)

c - 与正常函数调用相比仍然没有得到回调

c++ - 使用许多静态成员有问题吗?

database - Django : about external database model