预处理器定义重复

问题描述 投票:6回答:4

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

lib1.h

#define MYINT 1

lib2.h

#define MYINT 2

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

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

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

当我无法修改lib文件时,如何解决这个问题?

c++ c c-preprocessor
4个回答
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

3
投票

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

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

当然,如果MYINT是动态的东西并且您需要保持其实际内容,那么这不起作用。

由handy999编辑:在预处理器语句结束时没有分号。


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

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时使用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_LIB1替换文本MYINT然后进行重新扫描时,由于MYINT现在未定义,文本MYINT仍然存在,如果幸运的话,结果是编译器错误。

这项工作需要考虑的一件事

这项工作假设所需要的只是MYINT的数值,它被视为int常数值。因此,它假设使用MYINT的地方也可以使用const int

这意味着任何类型的令牌粘贴,#if测试或其他预处理器操作涉及处理MYINT被定义为可由预处理器用于其他宏操作的文本的文本在lib.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);函数,或者使用FUNCSTUFF()而不是myInt_lib1创建自己的MYINT宏。

© www.soinside.com 2019 - 2024. All rights reserved.