预处理器定义重复
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.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(myInt_lib1, &bThing);
中那样直接使用函数 funcStuff()
,或者制作您自己的 FUNCSTUFF()
宏版本,使用 myInt_lib1
而不是 [=13] =].
我有两个库,不幸的是它们定义了两个相同的预处理器定义(我需要使用):
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.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(myInt_lib1, &bThing);
中那样直接使用函数 funcStuff()
,或者制作您自己的 FUNCSTUFF()
宏版本,使用 myInt_lib1
而不是 [=13] =].