c++ - #include 文件派生自宏 __FILE__?

标签 c++ macros include c-preprocessor

观察下面的程序:

#include __FILE__
main(){}

预处理器陷入无限递归,包括自身内部的拷贝,并提示 main() 已经被定义。


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


例如,我想在 "foo.cpp" 中包含 "foo.h",但它是从 __FILE__.

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

最佳答案

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

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

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

The preprocessing tokens after #include in the directive are [macro-expanded]. The directive resulting after all replacements shall match one of the two previous forms [footnote: Note that adjacent string literals are not concatenated into a single string literal]. The method by which a sequence of preprocessing tokens between a < and a > preprocessing token pair or a pair of " characters is combined into a single header name preprocessing token is implementation-defined.

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's behavior is documented here ; 其他任何事都靠你自己。)

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

关于c++ - #include 文件派生自宏 __FILE__?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13485192/

相关文章:

c++ - void QTableWidget::setItemPrototype ( const QTableWidgetItem * item ) 如何克隆对象?

c - C 中的 with-open-file 宏

windows-7 - 将 VBS 脚本分配给键盘快捷键

c++ - 找不到头文件 (boost/bind.hpp)

c++ - 对象什么时候获取内存?

c++ - 什么 OpenGL 状态需要在新的共享上下文中重置?

c++ - 为什么省略 “#include <string>”有时只会导致编译失败?

包括使用 Fortran 预处理器进行显示

c++ - 如何在 OS X 上初始化 QOpenGLContext 以使用 OpenGL 3.3 版?

c++ - #define myptr int * 有什么问题?