#包含从宏__file__派生的文件

#include file derived from macro __FILE__?

本文关键字:派生 文件 file 包含      更新时间:2023-10-16

观察以下程序:

#include __FILE__
main(){}

预处理器陷入了无限递归中,在其内部包含其自身的副本,并抱怨已经定义了main()


如果我可以使用宏来包含文件,我可以基于__FILE__导出文件名并将其包含在内吗?


例如,我想在"foo.cpp"内部包含"foo.h",但从__FILE__派生。

  • ##将连接宏
  • 也可以对宏进行字符串化

可以用预处理器完成吗?

C标准规定了#include:的三种形式

#include <file>
#include "file"
#include ANYTHING ELSE

在前两种情况下,没有发生宏观扩展,因此没有办法改变行为。在第三种情况下,C99说(§6.10.2p4):

指令中#include之后的预处理标记为[宏扩展]。所有替换后产生的指令应与前两种形式中的一种匹配[脚注:注意,相邻的字符串文字不会连接到单个字符串文字中]。在<并且实现定义了一个>预处理令牌对或一对"字符组合成单个标题名称"预处理令牌

C++98§16.2p4中的措辞略有不同,但实际上相当。

任何带有"shall"的句子都提出了一个硬性要求:在这种情况下,如果ANYTHING ELSE扩展到除以<开始并以>结束或以"开始并以其结束的一系列标记之外的任何内容,则程序就是格式错误的。该令牌序列的确切解释是由实现定义的,但请注意,脚注特别禁止字符串文字串联。

因此,由于__FILE__的扩展是一个字符串常量,在#include中使用它的唯一方法是

#include __FILE__

正如你所发现的,这会导致无限递归,以及

#define LT <
#define GT >
#include LT __FILE__ etc GT

这对我可以方便地测试的所有编译器都有有趣但无用的影响。假设上面是在一个名为test.c:的文件中

  • GCC试图打开一个名为"test.c" etc的文件,其中包含引号和空格
  • clang更符合字面意思,它查找相同的文件名,但带有前导和尾随空格
  • MSVC宏仅扩展LT(我认为这是一致性冲突),抱怨没有匹配的>,然后尝试打开名为__FILE__ etc GT的文件

(GCC的行为记录在这里;你可以自己做任何其他事情。)

tl;博士:在预处理器内部没有办法做你想做的事情。我建议您计算出构建系统中要包含的文件的名称,并用-D开关通知编译器(在Unixy系统上,您需要双引号-DINCLUDEME='"includeme.h"';我不会说CMD)

我想出的最好的办法是:

#define foo(x) #x
#include foo(x)

prog.cpp:2:16:错误:x:没有这样的文件或目录