是否可以使用预处理器 __file__ 在 C 中生成 #define?

is it possible to use the preprocessor __file__ to generate a #define in C?

为了提高某些代码的美感,我希望 .h 文件包含一些代码,这些代码根据包含 .h 文件的文件设置#define。例如

#if (__file__ == "main.c")
#define MOUDLE MODULE_MAIN
#elif (__file__ == "foo.c")
#define MODULE MODULE_FOO
#endif

有什么办法可以完成这样的事情吗?主要动机是避免将 #define MODULE 放在每个文件的顶部,而是有一个定义映射的位置,并且只包含相同的 .h 文件。

不,你不能这样做。 #if只能做整数表达式。它对字符串一无所知,也不知道如何比较它们。

标准 C 预处理器不可能满足您的需求。通过阅读 C 标准进行检查,例如 n1570, or some C reference, or the wikipage on the C preprocessor, or the GNU cpp manual.

但请考虑另一种实现相同目的的方法:适当地 配置您的 build automation.

例如,如果您使用 make,则适当编辑您的 Makefile。如何做到这一点是一个非常不同的问题。

您可以为 make 设置一个规则,将特定的 -DMODULE=name 传递给 gcc

例如在我的 bismon (on github) the Makefile has near line 141 中类似于

modules/modbm_%.so: modules/modbm_%.c bismon.h  $(GENERATED_HEADERS) $(BM_HEADERS)
   $(CCACHE) $(LINK.c) -fPIC \
      -DBISMON_MODID=$(patsubst modules/modbm_%.c,_%,$<) -shared $< -o $@

要有创意。构建机器是源代码的一部分。适应它做你想做的事。不要指望标准预处理器能够满足您的所有需求。了解如何 invoke GCC (or your favorite compiler) on the command line. In , it is even worthwhile to generate some C file (perhaps some header file), and you might use another preprocessor (like GPP 或 m4) 为此目的。

记住编译器(特别是 GCCClang)是一个命令行程序,你应该从其他东西(比如makeninja 或许多其他构建自动化工具)。

(即使在微软系统上,编译器仍然是命令行的东西,但这个事实经常被忽略)

顺便说一句,我不喜欢很多IDE,因为它们隐藏构建过程,你需要掌握它。所以你需要配置它(例如,通过写你的 Makefile 或其他东西)并理解和定制它。

The main motivation is to avoid putting a #define MODULE at the top of every file and instead have one location where the mapping is defined

定义此类映射的单个位置可能应该是您的构建基础结构(例如,您的 Makefile 如果使用 make);您将调整它以使用适当的 -DMODULE=name 标志调用 gccclang(或大多数其他 C 编译器)。 (顺便说一句,您还需要 约定 源文件的基本名称是 C 标识符,因此您不会有任何 a-1.c 文件 - 因为 a-1 是不是标识符,而是 bcde.c

如果使用 GNU make,请阅读其 documentation,然后 运行 make -p 以了解与您的案例相关的规则(内置和自定义)。然后考虑一个类似于以下的规则:

%.o: %.c $(YOURHEADERS)
     $(COMPILE.c) -DMODULE=$(patsubst %.c,MODULE_%,$^) -c $< -o $@

根据您的需要调整该规则。 (如果你的文件名是小写的,你可能需要一些 $(shell ... ) 在里面,而你想要大写 MODULE)。

顺便说一句,您还可以生成 Makefile 的一部分(或者有一些 生成的 C 文件,您可以适当地 #include)。