预处理器定义重复

Preprocessor definition duplication

本文关键字:定义 处理器 预处理      更新时间:2023-10-16

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

lib1.h

#define MYINT 1

lib2.h

#define MYINT 2

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

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

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

当我不能修改lib文件时,我该如何解决这个问题?

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

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

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

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

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

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

我将采用的方法是从每个include文件派生include文件的扩展版本,该扩展版本将通过include文件本身之外的不同机制提供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

并且类似地对于CCD_ 7创建CCD_

#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值的相应副本、当使用lib1.h功能时使用myInt_lib1和/或当使用CCD13功能时使用myInt_lib2。但是,如果MYINT仅与库头文件本身一起使用,并且在实际使用库的任何地方都不需要CCD_14,则可以丢弃该语句。

我可以重新定义C++宏,然后再定义它吗?它展示了如何使用一些供应商的编译器和CCD_ 15指令来保存和恢复宏定义。然而,这似乎并不适用于你的帖子。

该帖子还有一个答案,描述了宏扩展的基本原理,以及为什么需要const int myInt_lib1 = MYINT;来保存MYINT的值,而不是像#define MYINT_LIB1 MYINT那样使用预处理器来保存MYINT的值。预处理器尽可能长时间地延迟宏的扩展,结果是,一旦使用#undef指令未定义MYINT,尝试使用#define MYINT_LIB1 MYINT中的预处理器宏来保存MYINT的值就不起作用。当预处理器首先用文本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))

期望任何使用该库的人将使用CCD_ 40而不是CCD_。要实现这一点,您需要像funcStuff(myInt_lib1, &bThing);中那样直接使用函数funcStuff(),或者制作自己版本的FUNCSTUFF()宏,使用myInt_lib1而不是MYINT

没有预处理器技巧:

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