#include文件派生自宏__FILE__?

时间:2012-11-21 01:50:27

标签: c++ macros include c-preprocessor

请遵守以下程序:

#include __FILE__
main(){}

预处理程序陷入无限递归,包括自身内部的副本,并抱怨main()已经被定义。


如果我可以使用宏来包含文件, 我可以根据__FILE__派生一个文件名并包含它吗?


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

是否可以使用预处理器完成?

2 个答案:

答案 0 :(得分:5)

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

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

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

  

指令中#include之后的预处理标记是[宏扩展]。所有替换后产生的指令应与前两个表单中的一个匹配[脚注:请注意,相邻的字符串文字不会连接成单个字符串文字]。一种预处理标记序列的方法,其中&lt;并且&gt;预处理令牌对或一对“字符组合成单个头名称预处理令牌是实现定义的。

C ++98§16.2p4中出现了略有不同但有效等效的措辞。

其中带有“shall”的任何句子都有强硬要求:在这种情况下,如果ANYTHING ELSE扩展为除<开头并以>开头的一系列标记之外的任何内容,则该程序格式不正确",或以__FILE__开头和结尾。对该令牌序列的确切解释是实现定义的,但请注意脚注特别禁止字符串 - 文字串联。

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

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

正如您所发现的那样,导致无限递归,

test.c

对我可以方便地测试的所有编译器都有趣但无用的影响。假设上面的文件名为"test.c" etc

  • GCC尝试打开名为LT的文件,其中包含引号和空格。
  • clang甚至更文字,并且查找相同的文件名但是带有前导和尾随空格。
  • MSVC宏扩展 >(我认为这是违规行为),抱怨没有匹配__FILE__ etc GT,然后尝试打开名为-D
  • 的文件

GCC's behavior is documented here;你自己做其他事情。)

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

答案 1 :(得分:0)

我想出的最好的是:

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

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