我试图弄清楚如何使用GCC为#include语句构建变量字符串。
我的想法是,对于我编写的每个源代码模块,我希望包含一个头文件,一个动态生成的C源代码,它是在构建过程的早期创建的。
生成此文件不是问题。不幸的是,包括它在内。
到目前为止我所拥有的是(身份。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 <FILENAME>
我认为问题在于include语句缺少引号。有什么想法吗?
5条答案
按热度按时间iqxoj9l91#
这是在Linux源代码树中完成的;参见compiler-gcc的第125行。h.最大值。
我试图弄清楚如何使用GCC为#include语句构建变量字符串。
此标记将
__GNUC__
的值粘贴到字符串中;linux/compiler-gcc__GNUC__
。h”,然后将结果串化。这可能是一个 gcc 预处理器扩展。这里有个例子
t1.h
t2.h
a. c
这里有两个编译,
两个编译器的输出都给出了预期的结果。
与Linux源代码一样,您可以取消gcc预定义的值。
echo | g++ -dM -E -
会给予一个列表。对于您的情况,您可以使用 makefile 向编译器传递一个定义,以允许动态包含生成的头文件,而无需更改源文件。但是,一个简单的替代方法是在模板源文件上运行
sed
等,并将其替换为已知的include名称。任何一种技术都适合生成测试夹具等。但是,对于编译器功能发现,这是一种更好的方法。对于使用IDE的程序员来说,这可能是他们唯一的选择。
xjreopfe2#
我相当肯定你不能做你想做的,
__FILE__
返回一个字符串,##
在令牌上工作,没有CPP字符串concat预处理器宏。通常情况下,这是由于两个字符串连续e。g的。将被C++解析器视为单个字符串。然而,
#include
是预处理器的一部分,因此无法利用这一事实。老答案:
你为什么要这么做
我确信这不是预处理器语法;你希望通过这个达到什么目的?你是否尝试过:
“{”可以解释您得到的错误。
yx2lnoni3#
Boost Preprocessor library中的BOOST_PP_STRINGIZE怎么样?它专门用于在名称周围添加引号。
rbpvctlc4#
暂时跳过整个包含语法的事情,我不明白你的代码想做什么。你说:
你给予它
main.c
并期望"main.c.iden"
,但它返回{"main.c", main.c.iden }
。相反,你在找这个吗?
ylamdve65#
你不能像这样使用预处理器。你必须为#include指令提供一个文件名,它不能是其他宏。