请遵守以下程序:
#include __FILE__
main(){}
预处理程序陷入无限递归,包括自身内部的副本,并抱怨main()
已经被定义。
如果我可以使用宏来包含文件,
我可以根据__FILE__
派生一个文件名并包含它吗?
例如,我想在"foo.h"
内包含"foo.cpp"
,但是从__FILE__
派生。
是否可以使用预处理器完成?
答案 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
:
LT
的文件,其中包含引号和空格。>
(我认为这是违规行为),抱怨没有匹配__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:没有这样的文件或目录