如何重命名 C 预处理器宏?

How to rename a C preprocessor macro?

考虑一个 (read-only third-party) header lib.h 具有:

#define XYZ 42

在源文件中,我想将单词 XYZ 用于不相关的目的,并且不希望替换为 42。但是,在同一个源文件中,出于其他目的,我也确实想从 lib.h 访问值 42 而无需对其进行硬编码。我如何 重命名 宏从 XYZLIB_XYZ

以下不起作用,因为预处理器在进行 LIB_XYZ 替换时需要 XYZ,但 XYZ 未定义:

#include "lib.h"
#define LIB_XYZ XYZ
#undef XYZ

有没有办法在 XYZ 丢失之前欺骗预处理器将 LIB_XYZ 扩展到它的最终值?

使用另一个 .c 文件,并将宏值分配给全局变量。

pre-processor 没有,至少,据我所知没有。

但是,对于您的示例中已知类型的简单常量,有一个解决方法。

#include <stdio.h>

// <xyz.h>

#define XYZ 42

// </xyz.h>

enum xyz_constants
{
  LIB_XYZ = XYZ,
};

#undef XYZ

#define XYZ 27

int
main()
{
  printf("old value: %d, new value: %d\n", LIB_XYZ, XYZ);
  return 0;
}

未显示stdio.h的绒毛,此代码为pre-processed以下

enum xyz_constants
{
  LIB_XYZ = 42,
};

int
main()
{
  printf("old value: %d, new value: %d\n", LIB_XYZ, 27);
  return 0;
}

您可以在某种程度上将其扩展到其他数据类型和某些 function-like 宏,但当然有限制。

无论如何,为什么需要特定标识符 XYZ?不能为您的宏使用不同的名称吗?

如果 lib.h 中的 XYZ 是一个 数字 [或各种常量],您可以使用 enum:

enum { LIB_XYZ = XYZ };
#undef XYZ

如果 XYZ 不是 以上,您必须创建(例如)myxyz.c 不是 包括 lib.h 并在那里使用 XYZ(其他文件可能包括 xyz.h

不同之处在于,#define LIB_XYZ XYZ 不会在那一行解析,只有当你以后使用它时才会解析,如:

foo(LIB_XYZ);

所以这行不通,因为您已经 #undef'ed XYZ

预处理器符号是一个名称。没有在保留内容的同时更改名称本身的预处理指令。例如,给定:

#define FOO 42

#define FOO(x, y)  x ## y (

如果不重复这些定义,就无法定义具有相同内容的名为 BAR 的宏。也就是说没有像这样的操作:

#alias BAR FOO  // nonexistent fantasy macro-cloning preprocessor directive

也不是这样的:

#rename BAR FOO // like #alias BAR FOO followed by #undef FOO

如果我们这样做:

#define BAR FOO  // for the #define FOO 42 case

这不是别名。宏 BAR 的定义使其替换标记序列是标记 FOO,而不是 42。如果 FOO 宏消失了,那么 BAR 就失去了意义。

另请注意,C 预处理器宏无法扩展为预处理指令,因此以下方法也不起作用:

 // wrong:
 #define MACRO_DEFINER(NAME) \
   #define NAME 42

 MACRO_DEFINER(FOO) // hoping for #define FOO 42: no such luck
 MACRO_DEFINER(BAR) // hoping for #define BAR 42: likewise

恐怕您必须后退几步才能找到替代策略来解决您要解决的任何问题。如果您遇到困难,请创建一个关于实际问题的新问题。

总是有代码生成:在构建时生成 C 或 C++。如果您只是调整生成系统,那么您可以梦想的任何文本替换或扩展都是可能的。

任何涉及 #undef XYZ 的解决方案都有破坏库头功能的风险。图书馆可能会做这样的事情:

#define XYZ 42 #define 宏(B) bloop(XYZ, B)

如果我们使用macro,那么如果我们重新定义XYZ,我们就会破坏它。

如果库因定义 XYZ 而为人所知,并且我们设法在使用该库的代码中成功地重新定义了它,这种情况会让未来的维护者感到困惑。 "Oh, this XYZ is not actually that library one; this programmer just wanted an unrelated XYZ."

这里最好的解决办法是停止使用 XYZ 并找到其他名称。适应您正在使用的库;不要和他们发生冲突。