什么是偶然的宏观替代?
在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
为什么这是一个很好的规则,以及需要此规则的最小和最大函数有什么特别之处?
答案 0 :(得分:8)
意外宏替换是无意中使用名称与函数冲突的宏。
情况Vera ++的检查旨在防止在行为不端的系统标头(最着名的<windows.h>
- 定义min
和max
宏,干扰应用程序定义的同名函数或即使使用标准库函数,例如std::min<T>
,std::max<T>
和std::numeric_limits<T>::min()
。 (已知其他名称也会引起冲突。)
由于宏不支持名称空间,因此将函数调用为 std
::min(...)
无效,因为预处理器仍然会扩展min
。要解决此问题,必须将此类函数调用为(function)(args...)
,这将阻止宏展开,前提是它被定义为#define function(arg1, arg2) ...
,min
和max
通常就是这种情况。另一个可用选项是在使用之前#undef
,但是在包含行为不当的标题之后。 Boost提供了自己的替代预防标记,尽管其自我描述性被其引入的混乱所抵消。
如果您控制了<windows.h>
的加入,则可以在加入之前#define NOMINMAX
,这将指示windows.h
不要定义min
和max
宏。
答案 1 :(得分:0)
问题是讨厌的库(或愚蠢的程序员)通常会定义您可能不期望的最大和最小宏。如果您的代码假设评估将由一个很好的函数完成,那么您将得到不正确的结果(甚至是未定义的行为)。通过指出,除非你确定你知道你正在使用的所有包含所定义的所有宏,否则linter是有帮助的,不存在与这些常见宏名称冲突的风险更安全。