#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏,以下是宏的声明方式
#define name( parament-list ) stuff
参数列表是由,隔开的一个符号表。 参数列表可带可不带,如果带参数列表的话必须与name紧邻否则会被解析成stuff的一部分。基于这个原理我们可以使用这个参数列表来实现函数。
需要注意的是宏参数和#define定义可以包含其他#define定义的符号。但是,宏不可以出现递归。
#define M 9
#define PRINT( FORMAT, VALUE ) \
printf("the value is " FORMAT"\n" , M+VALUE);
int main()
{
PRINT("%d" ,M);
return 0;
}
#与 ## 是俩个特殊符号,它们的含义如下
#define PRINT(VALUE) \
printf(#VALUE);
#define STRCAT(str1,str2) \
str1##str2
宏函数在预处理的时候就会替换成相应的语句,十分像c++里面的模板。它的优点比正常函数更高效因为不用栈帧的开销,但是它的缺点就是1 没有类型检测 2 可能具有副作用 3可能导致代码量的增加这样会导致源文件变得更大4没有返回值。本文直接给出宏函数的应用。
#define CHECK_AND_SET_OBJECT(obj,name,type) \
do \
{ \
if(obj == NULL) { \
printf("obj 为 NULL\n"); \
} \
type name(obj); \
} while(0)
有的时候我们想知道这个函数声明的形参是输入参数还是输出参数,我们可以这样使用宏
#define IN
#define OUT
#define INOUT
void Fun( OUT int * p); // p 为输出参数
void Fun2(IN int num); // num 为输入参数
有的时候可以把相关宏放头文件,通过增加头文件的宏,来修改代码,这个用法比较秀。如果下面这份代码,我们可以通过在Command.h中增加宏来改变 SomeThing.h 中 AllocHandler的逻辑,增加Get 则可以申请Get* 的数据,增加Set则可以申请Set* 的数据
Basic_Command.h
Command_Header(Get)
Command.h
enum CommantType {
ZERO = 0,
#define Command_Header(Command) Command##_TYPE,
#include "Basic_Command.h"
#undef Command_Header
MAXCOMMAND
};
SomeThing.h
void AllocHandler(CommandType type)
{
#define Command_Header(Command) \
if(Command##_TYPE == type) { \
Handlers[type] = new Command##Handler();
}
#include "Command.h"
#undef Command_Header
return ;
}
main.cc
#include "GetHandler.h"
#include "SomeThing.h"
int main() {
AllocHandler(1);
return 0;
}
宏可以简单的使用可变参数。只要在形参表最后一个加 … 即可。所有的可变参数使用__VA_ARGS__ 宏代替。 ## VA_ARGS 可消除 ## 前面的相应符号。如果不加##, LOG(“TEST”) 会被替换成 printf("%s:%d" “TEST”, func, LINE, ); ,从替换结果看多了一个 , 号。我们需要把这个 , 去掉所以得使用 ##去删除
LOG (format, ...) \
prinft ( "%s:%d" format , __func__, __LINE__, ## __VA_ARGS__);
如下面的实例宏 EXTERN_INSTANCE 就实现了模板函数 CreateInstance 和 DestroyInstance 函数。
MacroUtils.h
EXPORT_INSTANCE(type) \
void CreateInstance(type*& object) {
object = new type();
}
void DestroyInstance(type*& object) {
delete object;
object = NULL;
}
main.cc
class A {
};
EXPORT_INSTANCE(A);
int main()
{
A* p = NULL;
CreateInstance(p);
DestroyInstance(p);
return 0;
}