仅使用标准 C(C89、C99 或 C11)定义的工具,唯一的“禁用”机制是 #undef。
问题是没有“重新启用”机制。
正如其他人指出的那样,如果包含宏定义的头文件的结构使其不包含任何 typedef 或 enum 声明(这些不能重复;函数和变量声明可以重复),那么您可以 @987654322 @ 宏,在宏不生效的情况下执行您需要的操作,然后重新包含标头,可能在取消定义其对重新包含的保护之后。
当然,如果宏没有在标头中定义,那么在重构代码以使它们位于标头中之前,您将陷入困境。
还有一个技巧可用 - 如果宏是类函数宏而不是类对象宏。
#define nonsense(a, b) b /\= a
int (nonsense)(int a, int b)
{
return (a > b) ? a : b;
}
函数nonsense() 定义良好,尽管它前面有宏。这是因为宏调用 - 对于类似函数的宏 - 必须紧跟一个左括号(给或取空格,可能包括 cmets)。在函数定义行中,'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;
}
这段代码定义了一个名为min 的虚假函数,而且是荒谬的。并且没有宏的保护。
这是标准谨慎定义为“实现”保留哪些命名空间的原因之一。允许实现为它想要或需要的任何目的、它想要或需要的任何类型(类似函数或类似对象)定义宏,只要这些名称保留给实现。如果您作为 The Implementation 服务的消费者尝试使用或定义为实现保留的名称,您必须意识到您的代码迟早会中断,这将是您的错,而不是 The Implementation 的错实施。