#include文件派生自宏__FILE__?

Tre*_*key 5 c++ macros include c-preprocessor

请遵守以下程序:

#include __FILE__
main(){}
Run Code Online (Sandbox Code Playgroud)

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


如果我可以使用宏来包含文件,我可以根据__FILE__并包含它来获取文件名吗?


例如,我想"foo.h"在里面包括"foo.cpp",但是从中衍生出来__FILE__.

它可以用预处理器完成吗?

zwo*_*wol 5

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

#include <file>
#include "file"
#include ANYTHING ELSE
Run Code Online (Sandbox Code Playgroud)

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

#include指令中的预处理标记是[宏扩展].所有替换后产生的指令应与前两个表单中的一个匹配[脚注:请注意,相邻的字符串文字不会连接成单个字符串文字].将<和>预处理标记对或一对"字符"之间的预处理标记序列组合成单个标题名称预处理标记的方法是实现定义的.

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

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

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

#include __FILE__
Run Code Online (Sandbox Code Playgroud)

正如你所发现的那样,导致无限递归,并且

#define LT <
#define GT >
#include LT __FILE__ etc GT
Run Code Online (Sandbox Code Playgroud)

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

  • GCC尝试打开一个名为的文件"test.c" etc,其中包含引号和空格.
  • clang更加文字,并且查找相同的文件名,但带有前导和尾随空格.
  • MSVC宏观扩展LT(这是我经过深思熟虑后认为,这是一个符合违例),抱怨没有匹配>,然后尝试打开一个文件名为__FILE__ etc GT.

(海湾合作委员会的行为记录在这里 ;你可以自己做其他事情.)

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