如何在include中使用预处理器宏?

时间:2017-03-17 12:50:05

标签: c++ c preprocessor freetype2

我正在尝试使用自己的构建系统构建freetype2(我不想使用Jam,我准备花时间去搞清楚)。我在标题中发现了一些奇怪的东西。 Freetype定义了这样的宏:

#define FT_CID_H  <freetype/ftcid.h>

然后像这样使用它们:

#include FT_CID_H 

我没想到这是可能的,确实Clang 3.9.1抱怨:

error: expected "FILENAME" or <FILENAME>
#include FT_CID_H
  • 这些宏背后的基本原理是什么?
  • 这是有效的C / C ++吗?
  • 我怎样才能说服Clang解析这些标题?

这与How to use a macro in an #include directive?有关,但不同,因为这里的问题是关于编译freetype而不是编写新代码。

2 个答案:

答案 0 :(得分:11)

我将不按顺序解决你的三个问题。

  

问题2

     

这是有效的C / C ++吗?

是的,这确实有效。宏扩展可用于生成#include指令的最终版本。引用C ++ 14(N4140)[cpp.include] 16.2 / 4:

  

表单

的预处理指令
# include pp-tokens new-line
     允许使用

(与前两种形式中的一种不匹配)。 include之后的预处理令牌   在指令中处理就像在普通文本中一样处理(即,当前定义为宏名称的每个标识符是   替换为其预处理令牌的替换列表)。如果在所有替换之后产生的指令   与前两个表单中的一个不匹配,行为未定义。

提到的“之前的表单”是#include "..."#include <...>。所以是的,使用扩展到标题/文件以包含的宏是合法的。

  

问题1

     

这些宏背后的基本原理是什么?

我不知道,因为我从未使用过freetype2库。这将是其支持渠道或社区最佳回答的问题。

  

问题3

     

我如何说服Clang解析这些标题?

由于这是合法的C ++,您不必做任何事情。实际上,用户@Fanael有demonstrated,Clang能够解析这样的代码。您的设置中必定存在其他问题,或者您未显示的其他问题。

答案 1 :(得分:6)

  

这是有效的C / C ++吗?

用法有效C,只要宏定义在#include指令出现的范围内。具体来说,paragraph 6.10.2/4 of C11

  

表单

的预处理指令
# include pp-tokens new-line
     允许使用

(与前两种形式中的一种不匹配)。该   仅在处理指令中的include之后的预处理标记   与普通文本一样。 (当前定义为宏名称的每个标识符   被替换的预处理令牌列表取代。)   所有替换后产生的指令应与两者中的一个匹配   以前的表格。

(强调补充。)因为预处理器在C ++中具有与在C中相同的语义,据我所知,该用法在C ++中也是有效的。

  

这些宏背后的基本原理是什么?

我认为它旨在提供标题名称或位置的间接(通过提供宏的替代定义)。

  

我如何说服Clang解析这些标题?

再次提供宏定义在#include指令出现的范围内,您不应该做任何事情。如果确实如此,那么Clang就是这方面的错误。在这种情况下,在提交错误报告后(如果此问题尚不清楚),您可能需要手动扩展麻烦的宏引用。

但在此之前,请确保宏定义确实在范围内。特别是,它们可能受到条件编译指令的保护 - 在这种情况下,最好的行动方案可能是提供需要的任何宏定义(通过编译器命令行)来满足条件。如果您希望手动执行此操作,那么构建文档肯定会对其进行讨论。阅读构建说明。

相关问题