C++中的宏定义与MFC中的预处理器

一、C++中的宏定义

C/C++编译系统编译程序的过程为预处理、编译、链接。预处理器是在程序源文件被编译之前根据预处理指令对程序源文件进行处理的程序。预处理器指令以#号开头标识,末尾不包含分号。预处理命令不是C/C++语言本身的组成部分,不能直接对它们进行编译和链接。C/C++语言的一个重要功能是可以使用预处理指令和具有预处理的功能。C/C++提供的预处理功能主要有文件包含、宏替换、条件编译等。

1、文件包含
    预处理指令#include用于包含头文件,有两种形式:#include <xxx.h>,#include "xxx.h"。

2、宏替换

 ① 宏定义

宏定义的作用一般是用一个短的名字代表一个长的代码序列。宏定义包括无参数宏定义和带参数宏定义两类:

无参数宏定义。用一个用户指定的称为宏名的标识符来代表一个代码序列,这种定义的一般形式为#define 标识符 代码序列。

带参数宏定义。带参数宏定义进一步扩充了无参数宏定义的能力。带参数的宏定义的一般形式为#define 标识符(参数表) 代码序列,其中参数表中的参数之间用逗号分隔,在代码序列中必须要包含参数表中的的参数。在定义带参数的宏时,宏名与左圆括号之间不允许有空白符,应紧接在一起,否则变成了无参数的宏定义;带参数宏调用提供的实在参数个数必须与宏定义中的形式参数个数相同。

 ② 多行宏

宏定义在源文件中必须单独另起一行,换行符是宏定义的结束标志,因此宏定义以换行结束,不需要分号等符号作分隔符。如果一个宏定义中代码序列太长,一行不够时,可采用续行的方法。续行是在键入回车符之前先键入符号\,注意回车要紧接在符号\之后,中间不能插入其它符号,当然代码序列最后一行结束时不能有\。注意多行宏在调用时只能单独一行调用,不能用在表达式中或作为函数参数。

 ③ 宏展开

...具体介绍见参考文章。

 ④ 宏的独立性

...具体介绍见参考文章。

 ⑤ 宏调用与函数调用的区别

...具体介绍见参考文章。

⑥ 预定义宏

__DATE__,字符串常量类型,表示当前所在源文件的编译日期,输出格式为Mmm dd yyyy(如May 27 2006)。
    __TIME__,字符串常量类型,表示当前所在源文件的编译日期,输出格式为hh:mm:ss(如09:11:10)。
    __FILE__,字符串常量类型,表示当前所在源文件名,且包含文件路径。
    __LINE__,整数常量类型,表示当前所在源文件中的行号。
    __FUNCTION__,字符串常量类型,表示当前所在函数名。
    这些预定义宏在调试程序时是很有用的,因为你可以很容易的知道程序运行到了那个文件的那一行,是那个函数。
    用户除了可以在源文件的开头使用#define定义宏外,还可在编译器项目属性“预处理器”属性页定义宏。这种宏定义方式支持数字和字符串,一般形式为:标识符=数字或字符串常量,如果省略=以及后面的内容,则宏名标识符默认为整数1。定义宏的方法是在“预处理器定义”属性输入宏定义内容,多个宏定义之间用分号隔开。“预处理器定义”中的宏定义要先于源文件中的宏定义被处理,其有效范围为整个项目,除非在源文件中遇到重定义或用 #undef 指定取消宏定义名,否则该宏定义名在源文件中一直保持有效。

3、条件编译指令

#if,#ifndef,#ifdef,#else,#elif,#endif是比较常见条件编译预处理指令,具体见参考文章。

4、其它预处理指令

除了上面讨论的常用预处理指令外,还有三个不太常见的预处理指令:#line、#error、#pragma,下面分别介绍。具体介绍见参考文章。

本部分参考文章:https://blog.csdn.net/huang_xw/article/details/7648117

二、MFC中的预处理器

如上图中,在这里,WIN32、_DEBUGE、_UNICODE等其实是一些宏定义,在这里写上这些,相当于在本工程所有的文件中都写上了:

#define WIN32
#define _DEBUG
#define _UNICODE

这样,就可以达到一个多一个同一个代码在不同的配置环境在编译的结果文件不一样,从而实现跨平台。比如,在VC中,因为要有的环境是UNICODE,有些则不是,同一份代码为了在两种环境下都可以用,那么就会有以下宏定义(其实这就是twhar.h中的代码):

#ifdef  _UNICODE
typedef wchar_t     TCHAR;
#define __T(x)      L##x
#define _T(x)       __T(x)
#else
#define __T(x)      x
typedef char            TCHAR;
#endif 

那么,当你的环境中写了UNICODE时,这一段就会编译:

#define __T(x)      L##x
#define _T(x)       __T(x)

如果没有写UNICODE,那么上面这段就不编译,而是下面这段被编译:

#define __T(x)      x

这样,只要你的字符串用了_T("somechar"),那么,在有UNICODE的时候,就是L"somechar";在没有UNICODE在时候,就是它本身"somechar"了。

参考文章:https://www.cnblogs.com/Crysaty/p/6605419.html

三、预处理器的预定义宏汇总

符合ANSI的预定义宏:

__DATE__:表示当前源文件编译时的日期,格式为:月/天/年(Mmm dd yyyy)。

__FILE__:表示当前正在处理的源文件名称。

__LINE__:表示当前正在处理的源文件的行,可以用#line指令修改。

__STDC__:表示是ANSI C标准。只有在编译器选项指定了/Za,并且不是编译C++程序时,被定义为常整数1;否则未定义。

__TIME__:表示当前源文件的最近编译时的时间,格式为:小时/分/秒(hh:mm:ss)。

__TIMESTAMP__:表示当前源文件的最近修改日期和时间,格式为:Ddd Mmm dd hh:mm:ss yyyy,其中Ddd是星期的缩写。

 

Microsoft相关的宏

_ATL_VER:定义了ATL的版本。

_CHAR_UNSIGNED:设置默认的char类型是unsigned的。只有在编译器选项/J指定时才有定义。

__CLR_VER:指定了应用程序编译时的通用语言运行时(CLR)的版本。格式为:Mmmbbbbb,其中M是CLR的主版本,mm是CLR的次版本,bbbbb是build号。

__cplusplus_cli:只有在用/clr,/clr:pure或/clr:safe编译时才有定义。__cplusplus_cli的值是200406。

__COUNTER__:为一个整数,从0开始,每出现一次,其值增加1。可以使用__COUNTER__作为前缀来产生唯一的名字。

__cplusplus只有在编译C++程序时才有定义,一般用于区分C程序和C++程序。

_CPPLIB_VER:在程序中如果包含了任意C++标准库头文件,则_CPPLIB_VER有定义。用于显示正在使用的头文件的版本。

_CPPRTTI:用于标识编译器是否指定了RTTI。如果编译器选项中设定了/GR(打开运行时类型信息机制-RTTI),则_CPPRTTI有定义。

_CPPUNWIND:用于标识编译器是否打开异常处理。如果编译器选项中设定了/GX,则_CPPRTTI有定义。

_DEBUG:用于标识是Debug模式。在编译器指定了/LDd,/MDd或/MTd时才有定义。

_DLL:当编译器选项指定了/MD或/MDd(Multithread DLL)时才有定义。

__FUNCDNAME__:只有在函数内部才有效。返回该函数经编译器修饰后的名字。如果编译器选项中设定了/EP或/P,则__FUNCDNAME__是未定义。

__FUNCSIG__:只有在函数内部才有效,并且返回该函数的签名。一个函数的签名由函数名、参数列表、返回类型、内含的命名空间组成。如果它是一个成员函数,它的类名和const/volatile限定符也将是签名的一部分。在64位操作系统中,__cdecl是默认的函数调用方式。如果编译器选项中设定了/EP或/P,则__FUNCSIG__是未定义。

__FUNCTION__:只有在函数内部才有效。返回该函数未经修饰的名字。如果编译器选项中设定了/EP或/P,则__FUNCTION__是未定义。

_INTEGRAL_MAX_BITS:表示整数类型的最大位数(bits)。

_M_ALPHA:为DEC ALPHA平台定义。(现在已不支持)

_M_CEE:当使用/clr的任意形式(/clr:oldSyntax, 例如/clr:safe)编译时被定义。

_M_CEE_PURE:当使用/clr:pure编译时被定义。

_M_CEE_SAFE:当使用/clr:safe编译时被定义。

_M_IX86:为x86处理器架构定义。当值为300时说明是80386,值是400时说明是80486

_M_IA64:为Itanium处理器家族的64位处理器(IA64)架构定义。

_M_IX86_FP:表示编译器选项/arch的值。0:/arch未指定;1:指定/arch:SSE;2:指定/arch:SSE2

_M_MPPC:为Power Macintosh平台定义。(现在已不支持)

_M_MRX000:为MIPS平台定义。(现在已不支持)

_M_PPC:为PowerPC平台定义。(现在已不支持)

_M_X64:为x64处理器架构定义。 

_MANAGED:当编译器选项指定/clr时定义,其值为1。

_MFC_VER:指定MFC版本。例如:0x0700表示MFC version 7。

_MSC_BUILD:表示编译器版本号的修订号部分。修订号是以时期进行分割的版本号的第四部分。例如:如果VC++编译器的版本号是15.00.20706.01,则_MSC_BUILD的值为1。

_MSC_EXTENSIONS:当指定编译器选项/Ze(默认)时有定义,其值为1。

_MSC_FULL_VER:表示编译器的主,次版本号及build号。主版本号是整个版本号的第一部分,次版本号是整个版本号的第二部分,build号是整个版本号的第三部分。例如: 如果VC++编译器的版本号是15.00.20706.01,则_MSC_FULL_VER的值为150020706。可以在命令行键入cl /?来查看编译器的版本号。

_MSC_VER:表示编译器的主,次版本号。例如: 如果VC++编译器的版本号是15.00.20706.01,则_MSC_VER的值为1500。

__MSVC_RUNTIME_CHECKS:当指定编译器选项/RTC之一(/RTCs或/RTCu或/RTC1)时有定义。

_MT:当指定编译器选项/MD或/MDd(Multithreaded DLL)或/MT或/MTd(Multithreaded)时有定义。

_NATIVE_WCHAR_T_DEFINED:当指定编译器选项/Zc:wchar_t(将wchar_t视为内置类型)时有定义。

_OPENMP:当指定编译器选项/openmp时有定义,返回一个表示Visual C++中的OpenMP的日期的整数。

_VC_NODEFAULTLIB:当指定编译器选项/Zl(忽略默认库名)时有定义。

_WCHAR_T_DEFINED:当指定编译器选项/Zc:wchar_t或工程中包含的系统头文件中定义了wchar_t时有定义。

_WIN32:为Win32和Win64应用程序定义。总有定义。

_WIN64:为Win64应用程序定义。

_Wp64:当指定编译器选项/Wp64时有定义。

参考文章:https://www.cnblogs.com/whiteyun/archive/2011/07/07/2099918.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值