《宏篇》
预处理命令
参考链接:https://blog.csdn.net/akpe80900/article/details/102070084
预处理命令是什么
预处理语句,预处理语句是以#为起始标记,后面跟上预处理关键词。
预处理功能,例如,宏定义、文件包括、条件编译等
define
语法:
//用来定义宏
#define
使用:
//定义常量
#define MAX_WIDTH 100
//定义宏函数
#define getmax(a,b) a>b?a:b
undef
语法:
//用来取消宏
#undef
使用:
#define MAX_WIDTH 100
#undef MAX_WIDTH
ifdef ifndef
//只有定义所指宏情况下,才被编译
//#ifdef
//与上述相反
#ifndef
用法:
#ifdef MAX_WIDTH
char str[MAX_WIDTH];
#endif
#ifndef MAX_WIDTH
#define MAX_WIDTH 100
#endif
if elif else endif
//#if #elif(即else if) #else
// 判断条件为真时,才被编译
//#endif
// endif为结尾
用法:
#if MAX_WIDTH>200
#undef MAX_WIDTH
#define MAX_WIDTH 200
#elsif MAX_WIDTH<50
#undef MAX_WIDTH
#define MAX_WIDTH 50
#else
#undef MAX_WIDTH
#define MAX_WIDTH 100
#endif
char str[MAX_WIDTH];
pragram
用来配置编译器,本次不过多描述。
include
最常见的预处理命令
//1先在当前目录下寻找,然后再到默认路径下
#include "file"
//2直接在默认路径下找
#include <file>
line
当编译发生错误时,使用#line显示出错信息
#line 1 "assigning variable"
int a?;
报错会显示:"assigning variable", line 1 。
error
中断编译返回一个出错信息。
#ifndef __cplusplus
#error A C++ compiler is required
#endif
这个例子中如果__cplusplus没有被定义就会中断编译过程。
宏define
参考链接:https://www.cnblogs.com/fnlingnzb-learner/p/6903966.html
什么是宏?
宏#define是一个预处理命令,把一段字符串定义为一个标识符,这个标识符就是宏名。
定义宏
简单的定义:
#define PI 3.14
带参数的定义:
#define A(x) x
使用宏的优点
(1)方便修改,如果需要修改常量和方法,只需要找到对应宏进行修改,比较方便。
(2)提高运行效率,使用宏定义方法,能减少系统开销。
常见的宏
参考链接:https://blog.csdn.net/akpe80900/article/details/102070084
LINE
正在编译行对应源文件的行数
__LINE__
cout << "This is the line number "<< __LINE__;
FILE
被编译源文件的名称
__FILE__
DATA TIME
存储编译开始的日期,“Mmm dd yyyy”格式
__DATA__
存储编译开始的日期,“hh:mm:ss”格式
__TIME__
cplusplus
整数值,所有C++编译器都定义了这个常量为某个值。如果这个编译器是完全遵守C++标准的,它的值应该等于或大于199711L,具体值取决于它遵守的是哪个版本的标准。
__cplusplus
cout << "The compiler gives a "<<"__cplusplus value of "<< __cplusplus;
ON_MESSAGE
实现消息映射的宏,关于消息映射的内容,可参考《c++徒步》MFC篇——消息映射
BEGIN_MESSAGE_MAP(CMfctestDlg, CDialog)
ON_MESSAGE(WM_CLOSEFILLSET,OnCloseFillSet)
END_MESSAGE_MAP()
TRACE
参考链接:https://blog.csdn.net/u012559347/article/details/53081185
TRACE宏类似C语言中的Printf函数,输出想要的调试信息。
TRACE宏只有在调试状态下才有所输出,所以只对Debug版本的工程产生作用。Printf函数则无限制条件,任何情况均可以进行输出。
void OutputString(CString msg)
{
if (msg.IsEmpty() == false)
{
TRACE(msg);
TRACE("\n");
}
}
UNREFERENCED_PARAMETER
参考链接:https://blog.csdn.net/syflyhua/article/details/8989310
告诉编译器,已经使用了该变量,不必检测警告!
在VC编译器下,如果您用最高级别进行编译,编译器就会很苛刻地指出您的非常细小的警告。当你声明了一个变量,而没有使用时,编译器就会报警告:
“warning C4100: ''XXXX'' : unreferenced formal parameter.”
所以,为了让编译器不必检测你的警告,就使用UNREFERENCED_PARAMETER语句。比如:
int SomeFunction(int arg1, int arg2)
{
UNREFERENCED_PARAMETER(arg2)
...
}
HKEY_LOCAL_MACHINE
参考链接:https://baike.baidu.com/item/HKEY_LOCAL_MACHINE/10759123?fr=aladdin
HKEY_LOCAL_MACHINE保存了注册表里的所有与这台计算机有关的配置信息,只是一个公共配置信息单元,HKEY_LOCAL_MACHINE根键包含5个子键,分别为HARDWARE子键、SAM子键、SECURITY子键、SOFTWARE子键和SYSTEM子键。
FD_SET
参考链接:https://blog.csdn.net/miao19920101/article/details/69230891
未深入了解
FD_ZERO、FD_SET、FD_CLR、FD_ISSET
DECLARE_DISPATCH_MAP
在涉及MFC通过CHtmlView与js交互中用到,详细内容去《c++徒步》CHtmlView与js交互。
DECLARE_DISPATCH_MAP()
宏中的特殊字符
宏后的\
参考链接:https://blog.csdn.net/weixin_42425594/article/details/82225833
1 #define后面的""是续行符,表示下面一行是紧接着当前行的,一般用于将十分长的代码语句分几段写(语句本身要求必须是一行)。 这段代码就和下面的一样。
#define MIB_INFO_SIZE(S) (MAX_MIB_OFFSET + sizeof(S))
2 还可以写成如下格式,但要注意\后面除了换行回车不能有任何字符,空格也不行:
#define MIB_INFO_SIZE(S) (MAX_MIB_OFFSET + \
sizeof(S) \
)
双井号##
参考链接:https://www.cnblogs.com/zkwarrior/p/4869489.html
最近看com相关的资料,看到CCmdTarget实现com接口的时候,去读了一些宏的定义,在afxdisp.h头文件中
#define BEGIN_INTERFACE_PART(localClass, baseClass) \
class X##localClass : public baseClass \
本来这个宏定义很容易理解的,但是这里多出个X##,我真没见过这种用法,不晓得它是什么用意。
后来问了几个朋友也都不知道。
你知道么?
也许你也不知道~呵呵,最后我还是找到了相关的资料,解读了这个define,还顺便认识了另外两个不常用的define
#define Conn(x,y) x##y
#define ToChar(x) #@x
#define ToString(x) #x
x##y表示什么?表示x连接y,举例说:
int n = Conn(123,456); //结果就是n=123456;
char* str = Conn("asdf", "adf"); //结果就是 str = "asdfadf";
怎么样,很神奇吧
再来看#@x,其实就是给x加上单引号,结果返回是一个const char。举例说:
char a = ToChar(1);//结果就是a='1';
//做个越界试验
char a = ToChar(123);//结果是a='3';
但是如果你的参数超过四个字符,编译器就给给你报错了!error C2015: too many characters in constant :P
最后看看#x,估计你也明白了,他是给x加双引号
char* str = ToString(123132);// 就成了str="123132";
最后留几个小试验给大家去测测:
#define Dec(x,y) (x-y)
int n = Dec( A(123,1), 1230);
n = Conn(123, Conn(123,332) );
char* str = A("12", ToString( Dec(3,1));
结果会如何呢? 嘿嘿嘿嘿~
单井号#
参考链接:https://www.cnblogs.com/CityLcf/p/9913751.html
单井号#:构串操作符
构串操作符#只能修饰带参数的宏的形参,它将实参的字符序列(而不是实参代表的值)转换成字符串常量
#define STRING(x) #x#x#x
#define TEXT(x) "class"#x"Info"
//宏引用:
int abc = 100;
STRING(abc);
TEXT(abc);
//替换结果:
abcabcabc
classabcInfo
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?