【问题标题】:C preprocessor - Prepending path for existing define [duplicate]C预处理器 - 为现有定义添加路径
【发布时间】:2020-05-21 05:29:07
【问题描述】:

假设我有一个来自 gcc -D 选项的定义,例如

gcc -DBINDIR=\"/usr/bin\"

我想要的是为这个现有定义添加一个路径,因此 BINDIR 类似于 "/home/user/testbuild/usr/bin"

我尝试了什么:

#define STRINGIZE_NX(A)         #A
#define STRINGIZE(A)            STRINGIZE_NX(A)

#define PRE_PATH                "/home/user/testbuild"
#pragma message                 "PRE_PATH: " STRINGIZE(PRE_PATH)

#ifndef BINDIR
#   error "BINDIR must be defined"
#else
#   pragma message              "BINDIR: " STRINGIZE(BINDIR)
#   define TMP                  BINDIR
#   pragma message              "TMP: " STRINGIZE(TMP)
#   undef  BINDIR
#   define BINDIR               PRE_PATH TMP
#   pragma message              "BINDIR: " STRINGIZE(BINDIR)
#   undef  TMP
#endif

在查看编译器输出时,在我看来,TMP 没有按我预期的方式分配给 BINDIR 的值:

note: #pragma message: PRE_PATH: "/home/user/testbuild"
note: #pragma message: BINDIR: "/usr/bin"
note: #pragma message: TMP: BINDIR
note: #pragma message: "/home/user/testbuild" BINDIR

最后编译器会在定义应该连接的地方失败:

error: expected ')' before 'TMP'
#  define BINDIR    PRE_PATH TMP

我做错了什么?

感谢您的每一个帮助!

【问题讨论】:

  • 不可能。
  • 哪一部分不行?我试过this and the output seems ok.
  • 它部分回答了它,但我不明白为什么我不能将定义的值存储在另一个定义中。一旦我#undef 源,它也会在新定义中丢失 - 即使我之后取消定义它。所以我无法存储值而不是对原始 makro 进行某种引用? @Groo 好吧,如果使用新定义它可以工作,但我的意图是重用 BINDIR
  • 哦,您想更改BINDIR 宏本身吗?你确定这是真的需要吗?也许您可以分享一些细节,以确保我们没有在寻找 XY 问题。
  • Excatly - 真正的目的是在不交叉编译时调整一些目标路径。我确信实现这一目标的正确方法是正确更改构建环境,但在我的情况下,这需要重新处理一个非常大的项目的一堆 Makefile,所以我想到了一个替代方案

标签: c++ c c-preprocessor


【解决方案1】:

修改宏的值而不丢失其初始值是不可能的。您必须记住,定义宏并不等同于分配给变量。在后一种情况下,计算右侧表达式,并分配结果值。在前一种情况下,您为一系列标记定义一个名称(宏),直到宏展开后才会对它们进行评估。所以当你定义这个时:

#define TMP BINDIR

TMP 宏不“包含”路径“/usr/bin”,它实际上包含“BINDIR”。当TMP 扩展时,它会扩展为BINDIR,而BINDIR 又会扩展为“/usr/bin”。当您取消定义 BINDIR 时,它所拥有的值将丢失,TMP 扩展将导致只是“BINDIR”。

您可以对完整路径使用不同的宏,而不是 BINDIR。像这样的:

#define FULL_BINDIR PRE_PATH BINDIR

【讨论】:

  • 感谢您解释为什么我的方法不起作用,这似乎是解决问题的最简单方法
【解决方案2】:

我知道这不是您所要求的。然而,与其做一些晦涩难懂的预处理器魔法,不如把类似的东西放到头文件中:

#undef BIN_DIR
#define BIN_DIR bin_dir
extern char *bin_dir;

和代码文件之一和之前包括上述标题:

char *bin_dir = PRE_PATH BIN_DIR;

【讨论】:

  • 轻微挑剔:我建议使用char const * const bin_dir
  • 嗯,这是一个聪明的解决方法,但有了这个解决方案,我也不能使用原来的 BINDIR 定义,需要一个额外的变量。所以我想我更倾向于定义一个新的 makro #define BINDIR_NEW PRE_PATH BINDIR
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-08-18
  • 1970-01-01
  • 2020-04-22
  • 2018-02-10
  • 1970-01-01
  • 2015-06-18
  • 2021-06-02
相关资源
最近更新 更多