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

时间:2018-04-19 18:12:29

标签: c macros preprocessor

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

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

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

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

使用标准C预处理器,您想要的是不可能。通过阅读C标准进行检查,例如n1570,或C referencewikipage on the C preprocessorGNU cpp manual

但请考虑另一种实现相同目的的方法:正确配置 build automation

例如,如果您使用make,请相应地修改Makefile。如何做到这一点是一个非常不同的问题。

您可以拥有make的规则,该规则会将特定的-DMODULE= 名称传递给gcc

例如,在bismon (on github) Makefile 141附近有invoke GCC类似于

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

有创意。构建机制是源代码的一部分。适应它做你想要的。不要期望标准预处理器能够满足您的所有需求。在command line上了解如何some cases(或您最喜欢的编译器)。在GPP中,生成某些C文件(可能是某个头文件)甚至是值得的,您可以使用另一个预处理器(如GCC或m4)为此目的。

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

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

顺便说一句,我不喜欢很多documentation因为他们隐藏构建过程,你需要掌握它。因此,您需要对其进行配置(例如,通过编写Makefile或其他内容)并理解和定制它。

  

主要动机是避免在每个文件的顶部放置#define MODULE,而是在一个位置定义映射

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

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

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

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

顺便说一下,你也可以生成部分Makefile(或者有一些生成的 C文件,你可以适当地#include