我正在尝试包含一个由预处理器宏构建的文件,但由于有关令牌的规则,它似乎正在运行到墙上。我在这里使用了答案作为参考:Concatenate string in C #include filename,但我的情况不同之处在于我用于构造我的include的定义中有小数点。这是我目前无法通过预处理器阶段的内容: main.c中:
#include <stdio.h>
#include <stdlib.h>
#define VERSION 1.1.0
#define STRINGIFY(arg) #arg
#define INCLUDE_HELPER(arg) STRINGIFY(other_ ##arg.h)
#define INCLUDE_THIS(arg) INCLUDE_HELPER(arg)
#include INCLUDE_THIS(VERSION)
int main(int argc, char **argv) {
printf(INCLUDE_THIS(VERSION));
fflush(stdout);
#if defined (SUCCESS)
printf("\nSUCCESS!\n");
#endif
return EXIT_SUCCESS;
}
other_1.1.0.h:
#define SUCCESS
我是否使用#define VERSION 1_1_0
并相应地重命名了标题它会起作用(但由于我无法控制实际项目使用的头文件的名称,因此无法使用),但是{{1} }不是有效的预处理程序令牌。
编辑:
在对文档进行了一些挖掘之后,我发现1.1.0
是有效的1.1.0
;它是preprocessing number
的结果串联无效。无论如何,无法构建包含的问题仍然存在。
答案 0 :(得分:2)
通过一些实验,我想出了一个解决方案,虽然不理想,但仍然可行。
<section id="pageMain">
<div id="archive">
<ul>
<li>MARCH - 2018</li>
<li>FEBUARY - 2018</li>
<li>JANUARY - 2018</li>
<li>DECEMBER - 2017</li>
<li>NOVEMBER - 2017</li>
</ul>
</div>
<div id="aboutGame">
<span>
As if awakening from a deep sleep, you find yourself in a strange, contradictory world of ancient ruins and advanced technology. Tasked by your creator with solving a series of increasingly complex puzzles, you must decide whether to have faith, or to ask the difficult questions: Who are you? What is your purpose and what are you going to do about it? </span>
<img src="http://cdn.akamai.steamstatic.com/steam/apps/257510/ss_ded5cd1a34df5b4d9015f71caf35db247b2579c4.1920x1080.jpg?t=1498680189" height="500px" width="800px" />
</div>
</section>
我粘贴#define VERSION _1.1.0
#define STRINGIFY(arg) #arg
#define INCLUDE_HELPER(arg) STRINGIFY(other ##arg.h)
#define INCLUDE_THIS(arg) INCLUDE_HELPER(arg)
#include INCLUDE_THIS(VERSION)
和other_
,而不是粘贴1.1.0
和other
。我不确定为什么这是可以接受的,因为结果令牌是相同的,但它就是。
我仍然希望有一个解决方案,只允许我定义没有下划线的版本号,所以我会推迟接受这个答案,以防有人能提出更优雅的解决方案(适用于那些人不管怎么说都不需要下划线)
答案 1 :(得分:2)
一旦你停止考虑令牌连接,这很容易。字符串化适用于任何标记序列,因此无需强制其参数成为单个标记。你需要一个额外的间接,以便扩展参数,但这是正常的。
唯一的技巧是编写没有空格的序列,这是ID
的用途:
#define STRINGIFY(arg) STRINGIFY_(arg)
#define STRINGIFY_(arg) #arg
#define ID(x) x
#define VERSION 1.1.0
#include STRINGIFY(ID(other_)VERSION.h)
有关详细说明,请参阅https://stackoverflow.com/a/32077478/1566221。
答案 2 :(得分:1)
如果您将-DVERSION=1.1.0
作为编译行参数传递,而不是在源代码中对其进行硬连接,则没有什么可以阻止您使用make
或shell传递第二个定义连接。例如,在makefile中,您可能有:
VERSION = 1.1.0
VERSION_HEADER = other_${VERSION}.h
CFLAGS += -DVERSION=${VERSION} -DVERSION_HEADER=${VERSION_HEADER}
然后:
#include <stdio.h>
#include <stdlib.h>
#define STRINGIFY(arg) #arg
#define INCLUDE_HELPER(arg) STRINGIFY(arg)
#define INCLUDE_THIS(arg) INCLUDE_HELPER(arg)
#include INCLUDE_THIS(VERSION_HEADER)
int main(void)
{
printf("%s\n", INCLUDE_THIS(VERSION));
#if defined (SUCCESS)
printf("SUCCESS!\n");
#endif
return EXIT_SUCCESS;
}
基本上是删除了#define VERSION
行的代码,并使用字符串版本的VERSION_HEADER
而不是尝试在源代码中构造标题名称。您可能想要使用:
#ifndef VERSION
#define VERSION 1.1.0
#endif
#ifndef VERSION_HEADER
#define VERSION_HEADER other_1.1.0.h
#endif
对于某些合适的默认回退版本,以防运行编译的人未在命令行上指定信息。或者您可以使用#error You did not set -DVERSION=x.y.z on the command line
而不是设置默认值。
编译时(源文件hdr59.c
):
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -DVERSION=1.1.0 \
> -DVERSION_HEADER=other_1.1.0.h hdr59.c -o hdr59
$ ./hdr59
1.1.0
SUCCESS!
$
我会将三行宏和#include
行放入一个单独的小标题中,以便在需要版本标题时可以包含它。如果还需要默认设置,则会增加将代码放入单独的标头以供重用的重要性。该程序的源代码可能包含:
#include "other_version.h"
并且该标题将安排包含正确的文件,或多或少如图所示。