什么是偶然的宏观替代?

What is accidental macro substitution?

本文关键字:宏观 偶然 什么      更新时间:2023-10-16

什么是意外宏替换?

在Vera++ c++ linter中,规则T016规定:

应该防止对min和max函数的调用意外的宏替换。
x = max(y, z); // wrong, vulnerable to accidental macro substitution
x = (max)(y, z); // OK
x = max BOOST_PREVENT_MACRO_SUBSTITUTION (y, z); // OK

为什么这是一个很好的规则,最小和最大函数有什么特别之处需要这个规则?

意外宏替换是指无意中使用了与函数名称冲突的宏。

维拉++的检查是为了防止当错误的系统头(最著名的是<windows.h>)定义了minmax宏,这些宏会干扰应用程序定义的同名函数,甚至干扰标准库函数(如std::min<T>, std::max<T>std::numeric_limits<T>::min())时发生的情况。(其他名字也会引起冲突。)

由于宏不是名称空间感知的,因此将函数调用为 std ::min(...)没有帮助,因为min仍然由预处理器展开。为了解决这个问题,必须将这些函数调用为(function)(args...),如果将其定义为#define function(arg1, arg2) ...,则可以防止宏展开,这通常是minmax的情况。另一个可用的选项是在使用之前,但在包含错误的头文件之后,将它们#undef。Boost提供了自己的替代预防标记,尽管它的自描述性被它引入的混乱所抵消。

如果你控制了<windows.h>的包含,你也可以在#define NOMINMAX之前包含它,这将指示windows.h不定义minmax宏。

问题是讨厌的库(或愚蠢的程序员)通常会定义您可能意想不到的max和min宏。如果您的代码假设计算将由一个很好的函数完成,那么您将得到不正确的结果(甚至是未定义的行为)。linter指出,除非您确实知道正在使用的所有包含定义的所有宏,否则不要冒与这些通用宏名称冲突的风险,这是很有帮助的。