sor*_*rin 37 c++ gcc visual-c++ c-preprocessor
出于某种原因,我需要暂时禁用头文件中的某些宏,这#undef MACRONAME将使代码编译,但它将取消现有的宏.
有没有一种方法可以禁用它?
我应该提到你并不真正了解宏的值,而且我正在寻找交叉编译器解决方案(至少应该在GCC和MSVC中工作).
Kir*_*sky 83
在MSVC中,您可以使用push_macropragma,GCC 支持它与Microsoft Windows编译器的兼容性.
#pragma push_macro("MACRONAME")
#undef MACRONAME
// some actions
#pragma pop_macro("MACRONAME")
Run Code Online (Sandbox Code Playgroud)
Jon*_*ler 28
仅使用标准C(C89,C99或C11)定义的设施,唯一的"禁用"机制是#undef.
问题是没有"重新启用"机制.
正如其他人所指出的那样,如果包含宏定义的头文件是结构化的,那么它不包含任何typedef或enum声明(这些不能重复;函数和变量声明可以重复),那么你可以#undef宏,做什么你需要没有宏有效,然后重新包括标题,可能在取消定义其防止重新包装后.
如果宏没有在标题中定义,当然,在您重构代码以使它们位于标题中之前,您将陷入困境.
另一个技巧是可用的 - 如果宏是类似函数的宏而不是类似对象的宏.
#define nonsense(a, b) b /\= a
int (nonsense)(int a, int b)
{
return (a > b) ? a : b;
}
Run Code Online (Sandbox Code Playgroud)
该函数nonsense()定义正常,尽管它之前的宏.这是因为宏调用 - 对于类似函数的宏 - 必须紧跟一个左括号(给出或取出空格,可能包括注释).在函数定义行中,'废话'之后的标记是一个紧密的括号,因此它不是nonsense宏的调用.
如果宏是一个无参数的类对象宏,那么这个技巧就行不通了:
#define nonsense min
int (nonsense)(int a, int b)
{
// Think about it - what is the function really called?
return (a > b) ? a : b;
}
Run Code Online (Sandbox Code Playgroud)
这段代码定义了一个被称为虚假的虚假函数min.而宏没有保护.
这是标准小心定义为"实现"保留哪些名称空间的原因之一.允许实现为其期望或需要的任何目的定义宏,它们希望或需要任何类型(类似函数或类似对象),前提是这些名称保留给实现.如果您作为实现服务的使用者尝试使用或定义为实现保留的名称,您必须意识到您的代码迟早会破坏,并且这将是您的错,而不是The的错误.实现.