首页 > 系统相关 >C++ Windows.h max宏与std::max冲突问题解决

C++ Windows.h max宏与std::max冲突问题解决

时间:2023-06-13 12:00:54浏览次数:47  
标签:std min int max Windows include

  C语言引入的宏支持了一定程度的元编程,但它仅仅是简单的字符串替换,这种“六亲不认”的操作很容易导致一些编译错误。

  这篇文章介绍了一种场景:项目同时引入了老的C头文件,里面用宏定义了一些宏函数;还引入了C++的头文件,里面用其他方式定义了一些同名函数。具体到问题本身,这个老的头文件是Windows.h,它里面用宏定义了max函数,C++的标准库的algorithm也定义了max函数。

问题重现
简单的示例程序如下:

1 #include <Windows.h>
2 #include <algorithm>
3  
4 int main()
5 {
6     int m = std::max(5, 6);
7 }

编译时,会报错:

先看一下Windows.h中的max宏长啥样子。实际上max宏定义在minwindef.h头文件,而Windows.h引用了minwindef.h。max宏定义如下:

 1 #ifndef NOMINMAX
 2  
 3 #ifndef max
 4 #define max(a,b)            (((a) > (b)) ? (a) : (b))
 5 #endif
 6  
 7 #ifndef min
 8 #define min(a,b)            (((a) < (b)) ? (a) : (b))
 9 #endif
10  
11 #endif  /* NOMINMAX */

再来分析出错的原因,是程序里的max被认为是Windows.h中的宏,会进行替换,这样std::max(5, 6)会替换成:

std::(((5) > (6)) ? (5) : (6));

  这不是合法的C++程序,范围解析运算符后不是合法的名称,所以报以上的错误。使用min的时候也会出现类似情况。

  引入Windows.h而引起max或min冲突这个问题在Windows下开发挺常见的,因为很多程序都会直接或间接引用Windows.h头文件。

解决方案
  对于以上问题的解决方案,从宏定义的通用性和特殊性两方面着手。通用性,需要看C/C++的宏机制有哪些支持可以取消宏的替换。特殊性,需要看Windows.h有特殊的开关可以关闭max/min宏的替换。

方案一
使用括号括起std::max避免宏替换:

1 #include <Windows.h>
2 #include <algorithm>
3  
4 int main()
5 {
6     int m = (std::max)(5, 6);
7 }
8  

方案二
见招拆招,取消max定义。

1 #include <Windows.h>
2 #include <algorithm>
3  
4 #undef max
5  
6 int main()
7 {
8     int m = std::max(5, 6);
9 }

方案三
定义NOMINMAX宏,特定于max/min场景。

1 #include <Windows.h>
2 #include <algorithm>
3  
4 #define NOMINMAX
5  
6 int main()
7 {
8     int m = std::max(5, 6);
9 }

  这三种方案各有优缺,考虑到通用性上,方案一和方案二较好,缺点是必需把每个引起冲突的宏处理一遍;考虑到具体问题具体分析的原则,方案三较好,能批量处理相关的宏。在实际的项目中,我使用了方案二,毕竟引起冲突的宏并不多。

标签:std,min,int,max,Windows,include
From: https://www.cnblogs.com/ybqjymy/p/17477161.html

相关文章

  • Latex编译器推荐(面向初学者或者懒得折腾的朋友,主要针对windows用户)
    原文链接:https://blog.sciencenet.cn/blog-478347-1215384.html大家平时用的最多的排版工具想必就是Microsort的Word或者WPS了,所见即所得,Latex是另外一种排版工具,需要编译才可以生成pdf。相信大家在投稿的时候,会发现很多杂志都提供的textemplate。至于Latex好还是word好,这个已......
  • 乘风破浪,遇见最美Windows 11之现代Windows桌面应用开发 - .NET反编译神器dotPeek,免费
    什么是dotPeekhttps://www.jetbrains.com/decompiler/dotPeek是由鼎鼎有名的JetBrains开发的免费.Net反编译软件。其界面和VisualStudio一样现代。获取dotPeekhttps://www.jetbrains.com/decompiler/download/download-thanks.html?platform=windowsWebJetBrains.dotP......
  • MAXWELL两线圈静磁场仿真
    【1】初始界面 【2】选中MAXWELL3D仿真 默认为静磁场,刚好是需要的,无需改动  【3】放置原边线圈 主要需要修改的参数 PolygonSegments:Numberofcross_sectionsegments,0forcircle。截面多边形线段数,0表示圆。PolygonRadius:outerradiusofcross-sectonpoly......
  • Codeforces Round #221 (Div. 2)-D. Maximum Submatrix 2
    原题链接D.MaximumSubmatrix2timelimitpertestmemorylimitpertestinputoutputYouaregivenamatrixconsistingofdigitszeroandone,itssizeis n × m.Youare......
  • Educational Codeforces Round 20-C. Maximal GCD
    原题链接C.MaximalGCDtimelimitpertestmemorylimitpertestinputoutputn.Youshouldcreatesuch strictlyincreasing sequenceof k positivenumbers a1, a2, ..., ak,thattheirsumisequalto nGr......
  • 为Linux配置固定IP(Windows)
    配置固定IP地址目前我们虚拟机的Linux操作系统,其IP地址是通过DHCP服务获取的。DHCP:动态获取IP地址,即每次重启设备后都会获取一次,可能导致IP地址频繁变更。为什么需要配置固定IP地址原因1:办公电脑IP地址变化无所谓,但是要远程连接到Linux系统,如果IP地址经常变化就要频繁修改适......
  • Windows系统提示“ping”不是内部或外部命令
    Windows系统电脑/服务器在运行CMD命令提示符时提示“ping不是内部或外部命令,也不是可运行的程序或批处理文件”,遇到这种情况怎么办呢?今天我和你们分享解决办法。解决方法重新配置系统环境变量(演示的是Windows10系统)1、开始——控制面板——系统2、高级系统设置——高级——环境变......
  • kafka环境搭建(Windows10)
    1.安装Javajdk说明:kafka是使用zookeeper来进行集群部署,zookeerper运行环境依赖Java环境,因此需要安装Javajdk,并设置好系统环境变量。1.1下载jdk1.8华为提供的下载服务:https://repo.huaweicloud.com/java/jdk/官网下载地址:https://www.oracle.com/java/technologies/download......
  • 3dmax编辑常用按钮添加
    显示按钮,点击带笔的小图标修改按钮......
  • Windows服务器IIS日志存放位置 及 查看方法
    用户每打开一次网页,iis都会记录用户IP、访问的网页地址、访问时间、访问状态等信息,这些信息保存在iis日志文件里,方便网站管理员掌握网页被访问情况和iis服务器运行情况。如果网页被恶意访问(如注入数据库),日志中会有相应的记录,并且能看到注入者用什么代码注入,便于分析网站漏洞。i......