预处理器定义重复

Preprocessor definition duplication

我有两个库,不幸的是它们定义了两个相同的预处理器定义(我需要使用):

lib1.h

#define MYINT 1

lib2.h

#define MYINT 2

在我的程序中我需要同时使用它们:

#include <Lib1.h>
#include <lib2.h>
...
int myint = MYINT;

这里我遇到无法解析 MYINT 的错误。

无法修改lib文件怎么解决?

在第二个库替换它之前获取第一个库的 MYINT 值。

#include <Lib1.h>
int myInt1 = MYINT;
#undef MYINT
#include <lib2.h>
int myInt2 = MYINT;
#undef MYINT

当然,如果 MYINT 是动态的并且您需要保留其实际内容,那将不起作用。

由 handy999 编辑:预处理器语句末尾没有分号。

您可能 #undef MYINT 之前包含 header 作为解决方法。

#undef MYINT
#include <Lib1.h>
const int myint_lib1 = MYINT; // 1

#undef MYINT
#include <lib2.h>
const int myint_lib2 = MYINT; // 2

没有预处理器技巧:

lib1_handler.h

extern int lib1_handler_myint;
// or
int lib1_handler_myint_f();

lib1_handler.c

#include <Lib1.h>

int lib1_handler_myint = MYINT;
// or
int lib1_handler_myint_f() { return MYINT; }

lib2_handler.h

extern int lib2_handler_myint;
// or
int lib1_handler_myint_f();

lib2_handler.c

#include <Lib2.h>

int lib2_handler_myint = MYINT;
// or
int lib2_handler_myint_f() { return MYINT; }

main.c

#include "lib1_handler.h"
#include "lib2_handler.h"

int void () {
  return lib1_handler_myint || lib2_handler_myint_f();
}

我将采用的方法是从每个包含文件派生出扩展版本的包含文件,它将通过包含文件本身之外的不同机制提供 MYINT

因此,从 lib1.h 创建一个名为 lib1_ext.h 的包含文件,其中包含以下行:

#if !defined(MYLIB1_EXT_H_INCLUDED)
#define MYLIB1_EXT_H_INCLUDED
// ensure that MYINT is not defined no matter what order the include files are used
#undef MYINT
#include "lib1.h"
const int myInt_lib1 = MYINT;  // make a copy of the value of MYINT if it is needed
// make sure MYINT is undefined to allow the compiler to catch any dependencies on it
#undef MYINT
#endif

并且类似地为 lib2.h 创建 lib2_ext.h 如:

#if !defined(MYLIB2_EXT_H_INCLUDED)
#define MYLIB2_EXT_H_INCLUDED
// ensure that MYINT is not defined no matter what order the include files are used
#undef MYINT
#include "lib2.h"
const int myInt_lib2 = MYINT;  // make a copy of the value of MYINT if it is needed
// make sure MYINT is undefined to allow the compiler to catch any dependencies on it
#undef MYINT
#endif

现在使用库的任何功能时使用 MYINT 值的相应副本,myInt_lib1 使用 lib1.h 功能时 and/or myInt_lib2 使用 lib2.h 功能时。但是,如果 MYINT 仅与库头文件本身一起使用,并且在实际使用该库的任何地方都不需要,那么您可以丢弃该语句。

另请参阅 Can I redefine a C++ macro then define it back?,其中展示了如何使用某些供应商的编译器和 pragma 指令来保存和恢复宏定义。然而,它看起来并不真正适用于您的帖子。

该帖子还有一个答案,它描述了宏扩展的基础知识以及为什么需要 const int myInt_lib1 = MYINT; 来保存 MYINT 的值而不是像 #define MYINT_LIB1 MYINT 中那样使用预处理器保存 MYINT 的值。预处理器尽可能长时间地延迟宏的扩展,结果是尝试使用 #define MYINT_LIB1 MYINT 中的预处理器宏来保存 MYINT 的值一旦 MYINT 不起作用使用 #undef 指令未定义。当预处理器首先用文本 MYINT 替换文本 MYINT_LIB1 然后重新扫描时,由于 MYINT 现在未定义,文本 MYINT 仍然存在,结果是编译器如果你幸运的话会出错。

解决此问题需要考虑的一件事

此变通方法假定所需要的只是 MYINT 的数值,该数值被视为 int 常数值。所以它假设使用MYINT的地方也是可以使用const int的地方。

这意味着任何类型的标记粘贴、#if 测试或其他涉及处理文本的预处理器操作 MYINT 被定义为预处理器可用于其他宏操作的文本在预处理器包含和处理 lib.hlib2.h 的地方之外将无法正常工作。

这也意味着您不能指定编译器选项来声明 MYINT 作为条件编译的一部分,因为编译器选项创建的宏将被此变通方法忽略和消除。

因此,预处理器生成的源代码对 MYINT 作为每个包含文件之外的文本宏的任何依赖都会导致编译中断。

可能依赖的一个例子是 lib1.h 中的一个宏,它使用 MYINT 为函数创建一个额外的、看不见的参数,如:

int funcStuff (int a, struct b *pBthing);

#define FUNCSTUFF (pBthing)  funcStuff(MYINT, (pBthing))

期望任何使用该库的人都会使用 FUNCSTUFF(&bThing); 而不是 funcStuff (MYINT, &bThing);。要完成这项工作,您需要像在 funcStuff(myInt_lib1, &bThing); 中那样直接使用函数 funcStuff(),或者制作您自己的 FUNCSTUFF() 宏版本,使用 myInt_lib1 而不是 [=13] =].