C宏 – 动态#include

我试图弄清楚如何使用GCC为#include语句构建变量字符串。

我的想法是,对于我编写的每个源模块,我希望包含一个动态生成的C源头,它是在构建过程的早期创建的。

生成此文件不是问题。 不幸的是,包括它在内。

到目前为止我所拥有的是(identities.h):

// identities.h # define PASTER2(str) #str # define PASTER(str) PASTER2(str ## .iden) # define EVALUATOR(x) PASTER(x) # define IDENTITIES_FILE EVALUATOR(__FILE__) # include IDENTITIES_FILE 

理想情况下,这将使用(main.c):

 //main.c # include "identities.h" int main() {return 0;} 

在编译之前,预处理器将在一次传递中扩展为:

 //main.c (preprocessed) # include "main.c.iden" int main() {return 0;} 

我正在使用的两个间接级别(PASTER和EVALUATOR)是这篇文章的结果。

不幸的是,这不起作用,我留下了错误:

 obj/win32/dbg/main.o In file included from main.c:1:0: identities.h:42:1: error: #include expects "FILENAME" or  

我认为问题是include语句缺少引号..任何想法?

Boost预处理器库中的 BOOST_PP_STRINGIZE怎么样? 它专门用于在名称周围添加引号。

这实际上是在Linux源代码树中完成的; 参见compiler-gcc.h的第100行 。

 #define __gcc_header(x) #x #define _gcc_header(x) __gcc_header(linux/compiler-gcc##xh) #define gcc_header(x) _gcc_header(x) #include gcc_header(__GNUC__) 

我试图弄清楚如何使用GCC为#include语句构建变量字符串。

此令牌将__GNUC__的值粘贴到字符串中; “linux / compiler-gcc”__ __GNUC__ __“.h”然后将结果字符串化。 这可能是gcc预处理器扩展。

这是一个例子,

t1.h

 #define FOO 10 

t2.h

 #define FOO 20 

AC

 #ifndef VERSION #define VERSION 1 #endif #define __gcc_header(x) #x #define _gcc_header(x) __gcc_header(t##xh) #define gcc_header(x) _gcc_header(x) #include gcc_header(VERSION) #include  int main(void) { printf("FOO is %d\n", FOO); return 0; } 

这是两个编译,

 g++ -oa a.cc g++ -DVERSION=2 -oa a.cc 

任一编译的输出都给出了预期的结果。

与Linux源代码一样,您可以键入gcc预定义值。 echo | g++ -dM -E - echo | g++ -dM -E -将给出一个列表。

对于您的情况,您可以使用makefile将定义传递给编译,以允许动态包含生成的头而不更改源。 但是,一个简单的替代方法就是在模板源文件上运行sed等,并用已知的include名称替换它。

这两种技术都适用于生成测试夹具等。但是,对于编译器function发现,这是一种更好的方法。 对于使用IDE的程序员来说,这可能是他们唯一的选择。

我相当肯定你不能做你想要的,__ FILE__返回一个字符串,##在令牌上工作,没有CPP字符串concat预处理器宏。 通常这是由于两个串连续的事实而得到的

 "Hello" " World" 

将被C ++解析器视为单个字符串,但#include是预处理器的一部分,因此无法利用这一事实。

老答案:

你为什么做这个

 { #str, str ## .iden } 

我确定这不是预处理器语法,你希望通过它实现什么? 你有没有尝试过:

 str ## .iden 

‘{‘可以解释你得到的错误。

你不能像这样使用预处理器。 你必须为#include指令提供一个文件名,它不能是其他一些宏。

暂时删除整个包含语法的东西,我不明白你的代码试图做什么。 你说:

 # define PASTER(str) { #str, str ## .iden } 

你给它main.c并期望"main.c.iden" ,但返回{"main.c", main.c.iden }

相反,你在寻找这个吗?

 #define PASTER2(str) #str #define PASTER(str) PASTER2(str ## .iden)