《宏篇》

预处理命令

参考链接: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 = 100STRING(abc);
TEXT(abc);
//替换结果:
abcabcabc
classabcInfo
posted @   Fusio  阅读(69)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示
目录导航
目录导航
《宏篇》
预处理命令
预处理命令是什么
define
undef
ifdef ifndef
if elif else endif
pragram
include
line
error
宏define
什么是宏?
定义宏
使用宏的优点
常见的宏
LINE
FILE
DATA TIME
cplusplus
ON_MESSAGE
TRACE
UNREFERENCED_PARAMETER
HKEY_LOCAL_MACHINE
FD_SET
DECLARE_DISPATCH_MAP
宏中的特殊字符
宏后的\
双井号##
单井号#
发布于 2023-05-06 11:15