我正试图弄清楚如何使用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)是this帖子的结果。
不幸的是,这不起作用,我留下了错误:
obj/win32/dbg/main.o
In file included from main.c:1:0:
identities.h:42:1: error: #include expects "FILENAME" or <FILENAME>
我认为问题在于include语句缺少引号..任何想法?
答案 0 :(得分:7)
这实际上是在Linux源代码树中完成的;请参阅line 100 of compiler-gcc.h。
#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__)
我正试图弄清楚如何使用GCC为#include语句构建变量字符串。
此标记将__GNUC__
的值粘贴到字符串中; “linux / compiler-gcc”__GNUC__
“。h”然后将结果字符串化。这可能是 gcc 预处理器扩展。
这是一个例子,
#define FOO 10
#define FOO 20
#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;
}
这是两个编译,
g++ -o a a.cc
g++ -DVERSION=2 -o a a.cc
任一编译的输出都会给出预期的结果。
与Linux源代码一样,您可以键入gcc预定义值。 echo | g++ -dM -E -
会列出一个清单。
对于您的情况,您可以使用 makefile 将定义传递给编译,以允许动态包含生成的标头而不更改源。但是,一个简单的替代方法就是在模板源文件上运行sed
等,并用已知的包含名称替换它。
这两种技术都适用于生成测试夹具等。但是,对于编译器功能发现,这是一种更好的方法。对于使用IDE的程序员来说,这可能是他们唯一的选择。
答案 1 :(得分:3)
我相当肯定你不能做你想做的事,__ FILE__返回一个字符串,##在令牌上工作,没有CPP字符串concat预处理器宏。通常情况下这是由于连续两个字符串这样的事实,例如
"Hello" " World"
C ++解析器将视为单个字符串,但#include是预处理器的一部分,因此无法利用这一事实。
旧答案:
你为什么这样做
{ #str, str ## .iden }
我确定这不是预处理器语法,你希望通过它实现什么?你有没有尝试过:
str ## .iden
'{'可以解释你得到的错误。
答案 2 :(得分:1)
来自Boost Preprocessor library的BOOST_PP_STRINGIZE怎么样?它专门用于在名称周围添加引号。
答案 3 :(得分:0)
暂时删除整个包含语法,我不明白你的代码试图做什么。你说:
# 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)
答案 4 :(得分:-1)
你不能像这样使用预处理器。你必须为#include指令提供一个文件名,它不能是其他一些宏。