如何暂时禁用C/C++中的宏扩展?

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)

  • 很高兴知道存在,所以很好的答案,但这是可怕的. (15认同)
  • 这就是人们不断告诉我们*宏是邪恶的原因*.迟早有人会创建一个名为"new"的宏来做一些愚蠢的事...... (3认同)

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的错误.实现.