C宏 - 动态#include

J T*_*J T 9 c macros include c-preprocessor

我试图弄清楚如何使用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
Run Code Online (Sandbox Code Playgroud)

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

//main.c

# include "identities.h"

int main() {return 0;}
Run Code Online (Sandbox Code Playgroud)

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

//main.c (preprocessed)

# include "main.c.iden"

int main() {return 0;}
Run Code Online (Sandbox Code Playgroud)

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

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

obj/win32/dbg/main.o
In file included from main.c:1:0:
identities.h:42:1: error: #include expects "FILENAME" or <FILENAME>
Run Code Online (Sandbox Code Playgroud)

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

art*_*ise 7

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

#define __gcc_header(x) #x
#define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h)
#define gcc_header(x) _gcc_header(x)
#include gcc_header(__GNUC__)
Run Code Online (Sandbox Code Playgroud)

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

此标记将值粘贴__GNUC__到字符串; "linux/compiler-gcc" __GNUC__ ".h"然后将结果字符串化.这可能是gcc预处理器扩展.

这是一个例子,

t1.h

#define FOO 10
Run Code Online (Sandbox Code Playgroud)

t2.h

#define FOO 20
Run Code Online (Sandbox Code Playgroud)

AC

#ifndef VERSION
#define VERSION 1
#endif
#define __gcc_header(x) #x
#define _gcc_header(x) __gcc_header(t##x.h)
#define gcc_header(x) _gcc_header(x)
#include gcc_header(VERSION)
#include <stdio.h>

int main(void)
{
        printf("FOO is %d\n", FOO);
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是两个编译,

g++ -o a a.cc
g++ -DVERSION=2 -o a a.cc
Run Code Online (Sandbox Code Playgroud)

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

与Linux源代码一样,您可以键入gcc预定义值. echo | g++ -dM -E -会给出一个清单.

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

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


Mik*_*son 1

Boost 预处理器库中的 BOOST_PP_STRINGIZE 怎么样?它是专门为在名称周围添加引号而设计的。

  • BOOST_PP_STRINGIZE 不只是添加井号 #。该文档特别指出,与仅使用 # 相反,该宏实际上允许扩展其参数(而 # 则不允许)。经过几次测试后,您的主要问题似乎是 __FILE__ 已扩展为引号之间的文件名,并且删除它们是不可能的(至少据我所知)。 (4认同)
  • 是的,我已经求助于使用 GCC 和 Make: gcc -c -DEVALUTOR_ARGUMENT=$&lt; $&lt; (2认同)