如何暂时禁用C / C ++中的macros扩展?
出于某种原因,我需要暂时禁用头文件中的一些macros, #undef MACRONAME
undef #undef MACRONAME
将使代码编译,但它将#undef MACRONAME
现有的macros。
有没有办法只是禁用它?
我应该提到你并不知道macros的值,而且我正在寻找一个交叉编译器解决scheme(至less应该在GCC和MSVC中工作)。
在MSVC中,您可以使用push_macro
编译指示,GCC 支持它与Microsoft Windows编译器的兼容性。
#pragma push_macro("MACRONAME") #undef MACRONAME // some actions #pragma pop_macro("MACRONAME")
仅使用由标准C(C89,C99或C11)定义的设施,唯一的“禁用”机制是#undef
。
问题是没有“重新启用”机制。
正如其他人指出的那样,如果包含macros定义的头文件的结构不包含任何typedef或枚举声明(这些不能重复;函数和variables声明可以重复),那么你可以#undef
macros,在没有生效的macros的情况下做你所需要的,然后重新包含标题,可能在取消定义重新包含的保护之后。
如果在头文件中没有定义这些macros,当然,在重构代码以使它们位于头文件中之前,这些macros是被卡住的。
另一个技巧是可用的 – 如果macros是函数macros而不是对象macros。
#define nonsense(a, b) b /\= a int (nonsense)(int a, int b) { return (a > b) ? a : b; }
函数nonsense()
被定义为罚款,尽pipe在它之前的macros。 这是因为一个macros的调用 – 对于一个类似于函数的macros – 必须紧跟着一个左括号(给予或占用空白,可能包括注释)。 在函数定义行中,“无意义”之后的标记是一个右括号,所以它不是nonsense
macros的调用。
如果macros是一个没有参数的类似macros的对象,那么这个技巧就无法工作:
#define nonsense min int (nonsense)(int a, int b) { // Think about it - what is the function really called? return (a > b) ? a : b; }
这段代码定义了一个被称为min
的伪造函数,并且是无意义的。 macros观上没有保护。
这就是为什么标准要仔细定义为“实现”保留哪些名称空间的原因之一。 允许实现为其需要或需要的任何目的定义任何types的(类似于函数的或类似于对象的)macros,只要这些名称是为实现保留的。 如果您作为The Implementation服务的使用者尝试使用或定义一个为实现保留的名称,那么您必须意识到您的代码迟早可能会中断,而这将是您的错,而不是The实现。
macros使我的膝盖变得虚弱,但是最通用的解决scheme不是重构你的代码,所以你不需要在同一个源文件中重新启用macros。 不可能将一些代码提取到一个单独的函数和一个单独的源文件中,在那里你可以解开这个有问题的macros。
macros来自一些头文件,所以你应该有权访问它们的值。 然后你可以做类似的事情
#include <foo.h> // declares macro FOO // Do things with FOO #undef FOO // do things without FOO #include <foo.h> // reenable FOO
然后你的标题应该沿着这些线devise
#ifndef FOO #define FOO do_something(x,y) #endif
编辑:
你可能会认为这很简单:
#ifdef macro #define DISABLED_macro macro #undef macro #endif // do what you want with macro #ifdef DISABLED_macro #define macro DISABLED_macro #endif
但它不是(就像下面的例子演示)!
#include <iostream> #include <limits> #include <windows.h> #ifdef max #define DISABLED_max max #undef max #endif int main() { std::cout << std::numeric_limits<unsigned long>::max() << std::endl; #ifdef DISABLED_max #define max DISABLED_max #endif std::cout << max(15,3) << std::endl; // error C3861: "max": identifier not found return 0; }
在macros上使用#undef
并重新包含原始头文件也是不太可能的,因为头文件守护程序。 所以剩下的就是使用push_macro/pop_macro #pragma
指令。
#pragma push_macro("MACRO") #undef MACRO // do what you want #pragma pop_macro("MACR")