点击文末“了解更多”链接,系统学习Windows客户端开发。
宏是C/C++语言的一个重要特性,因为其代码可读性差,难于调试,经常被人诟病。但是,宏也有其显著的优点,比如简化程序员编写重复代码,某些场景只有宏才能实现,比如根据预定义宏_DEBUG,决定调试版本才启用调试断言ASSERT。C/C++程序员不使用宏,是不切合实际。
宏的使用包括:
定义无参数宏,一般用于定义常量;
定义有参数宏;
定义可变参数宏;
将宏参数变成字符串;
将宏参数与其它字符相连接;
下面以计算某种圆形材料费用为例说明宏定义的使用,此演示纯粹为了介绍宏定义使用,不是推荐大家这么编写代码。
第13行定义无参数宏PI,如果实现文件.cpp内部使用某个常量,更加推荐显示定义常量变量。如果常量是定义在头文件,被其它模块引入使用,推荐使用宏。
第16行定义有参数宏CIRCUM计算周长,宏参数r为半径,宏参数r需要括号,否则当r取值为3+5时,宏展开2*PI*3+5,将不是所预期的。
第19行定义可变参数宏LOG用于打印日志,打印日志需要格式化输出,参数个数是不确定的,宏展开是调用printf函数,printf函数有一个固定参数 const char* Format,然后是可变参数,所以LOG要求至少一个参数,使用预定义宏__VA_ARGS_作为printf函数,编译器编译时发现预定义宏__VA_ARGS_会将宏LOG第一参数设置给Format,其它参数作为可变参数。
第22行宏定义使用符号#将宏参数NAME变成字符串,比如STR(x)展开后为“x”
第25行宏定义使用符号##将宏参数与其它字符串拼接,比如DEFINE_GLOBAL_VAR(price, 10)宏展开后int g_price = 10; 定义全局变量时为了避免命名冲突,一般变量名会使用宏参数拼接而成。
预定义宏辅助打印日志
Visual Studio编译器预定义三个宏:__FILE__, __LINE__, __FUNCTION_,其中__FILE__表示当前代码所在的源文件名称,__LINE__表示当前代码所在的行数,__FUNCTION_表示当前代码所在的函数名称,打印日志时输出__FILE__和__LINE__信息,有助于通过日志找到对应的源码。
预定义宏辅助跨平台实现
各平台C/C++编译器都会预定义平台,比如Android NDK编译时预定义__ANDROID__表示Android平台,Visual Studio编译时预定义__WIN32__表示Windows平台。C/C++提供#ifdef #elif #ifndef用于判断宏是否定义,根据预定义宏可以编写跨平台代码。比如,实现网卡工具类用于获取网卡的MAC地址等信息,获取网卡信息在不同平台都有自己的API可以调用实现,于是抽象出接口,不同平台进行不同实现,实例化时根据预定义宏实例化不同的实现类。