Windows.h引入"陷阱"
当你引入#include <Windows.h>头文件后,再使用一些标准库中的函数时,是否会出现编译错误的问题?接下来就简单窥探下具体原因。
一、“陷阱”在哪?
看如下的几行简单代码:
1 #include <Windows.h> 2 3 int main() 4 { 5 std::max(1, 10); // 编译错误 6 7 return 0; 8 }
提示::非法,我们去掉Windows.h头文件后就编译通过了:
如果感觉奇怪,可以将鼠标放到提示错误的函数上面,就看到问题的原因:
好端端地一个标准库函数被宏定义替换,这就是引入Windows.h头文件的“陷阱”之一。
二、导致“陷阱”的根源
C++编译器编译源文件需要经历几个步骤:预处理 -> 编译 ->链接。其中预处理之一就是宏替换,我们通过IDE快捷方式跳转到max定义的地方:
在预处理Windows.h头文件的时候将std::max(1, 10)简单替换成:std::(((1) > (10)) ? (1) : (10)),编译器在编译的时候就报了上述的错误。不通过IDE,我们也可以通过预处理文件查看替换后的信息:
是不是验证了上面的说法?下面是visual studio IDE生成预处理文件的配置截图:
三、必须要引入Windows.h头文件怎么办?
如果我们的项目中必须要引入Windows.h头文件,但是我们喜欢用标准库中的函数(std::max, std::min)时该如何避免这个“陷阱”呢?其实很简单,直接使用预处理指令取消掉Windows.h中定义的max和min宏,预处理指令如下:
1 #include <Windows.h> 2 #include <algorithm> 3 #undef max // 这行预处理指令 4 5 int main() 6 { 7 std::max(1, 10); 8 9 return 0; 10 }
编译通过。当然,引入Windows.h头文件的"陷阱"不只有这个,还有其他的问题,比如头文件包含位置问题导致编译的问题,其实很大程度在预处理的时候出现的问题,需要大家在平时的时候多积累和注意。最好是不涉及Windows API的就不要包含这个头文件了。