什么是偶然的宏观替代?
What is accidental macro substitution?
什么是意外宏替换?
在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>
)定义了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
宏。
问题是讨厌的库(或愚蠢的程序员)通常会定义您可能意想不到的max和min宏。如果您的代码假设计算将由一个很好的函数完成,那么您将得到不正确的结果(甚至是未定义的行为)。linter指出,除非您确实知道正在使用的所有包含定义的所有宏,否则不要冒与这些通用宏名称冲突的风险,这是很有帮助的。
- MSVC中的宏观扩展问题
- C++宏观参数
- 为什么在一个地方需要双倍英镑,而在这个宏观上不需要其他地方?
- 我的宏观有点顽皮
- 如何使宏观上的任何容器都可以工作
- 悬挂if和宏观
- 在海湾合作委员会中加快宏观预处理的任何方法
- 打印宏观值而不知道宏的数量
- 是否有一种无偶然的方法来吸收类标头文件
- 可以通过偶然的C/C 销毁文件
- PVS Studio抱怨危险的宏观表达
- 使用宏观使用宏来明确实例化类成员函数
- 最小宏观的奇怪行为
- 算术表达式背景下的宏观扩展
- 具有多行字符串宏观的Getter/Setter生成
- GCC与Visual Studio宏观扩展
- 这些宏观定义的目的是什么
- 关于宏观用法的建议
- C 预处理器中的宏观危害
- 什么是偶然的宏观替代?