预处理程序定义重复

时间:2019-01-10 11:02:21

标签: c++ c c-preprocessor

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

lib1.h

#define MYINT 1

lib2.h

#define MYINT 2

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

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

在这里,我有一个无法解决MYINT的错误。

当我无法修改lib文件时该如何解决?

4 个答案:

答案 0 :(得分:5)

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

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

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

答案 1 :(得分:3)

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

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

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

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

答案 2 :(得分:0)

没有预处理器技巧:

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();
}

答案 3 :(得分:0)

我将采用的方法是从每个包含文件中获得包含文件的扩展版本,该扩展版本将通过包含文件本身之外的其他机制提供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,和/或在使用{时,请使用myInt_lib2 {1}}功能。但是,如果lib2.h仅与库头文件本身一起使用,并且在实际使用该库的任何地方都不需要,那么您可以丢弃该语句。

另请参见Can I redefine a C++ macro then define it back?,其中显示了如何使用某些供应商的编译器和MYINT指令来保存和恢复宏定义。看起来,这似乎不适用于您的帖子。

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

要解决的一件事

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

这意味着涉及处理const int被定义为可以由预处理程序用于其他宏操作的文本的文本的任何类型的令牌粘贴,#if测试或其他预处理程序操作都不是将在预处理器包含并处理的MYINTlib.h之外的地方正常工作。

这也意味着您不能指定编译器选项来声明lib2.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()或使用funcStuff(myInt_lib1, &bThing);而不是{{1 }}。