预处理指令: 以#开头的行都是预处理指令,用于指示编译器做一些预处理工作,预处理实现的是文本替换而不是值替换,预处理指令不是语句,所以行尾不要加分号。
#define为宏定义,有两种用法:
1)定义一个数值
#define Pi 3.14 //注意宏是把Pi换成3.14而不是把3.14换成Pi
2)定义一个算式
以下两个宏定义通通不行:
#define int a
#define 4 a
当进行了#define a 4的宏定义后,a就不能再作为变量了,即int a = 7就要报错。
以下是OpenCV的宏:
#define CV_8U 0表示的是CV_8U会在预处理时被编译器替换为0,注意的是这个替换是单向的,即只能把CV_8U看做0,不能把0看做CV_8U!有什么意义呢?举个例子,因为这样就可以用作判断了,增加可读性,如此时的type是CV_8U,可以用if(type==CV_8U)语句,因为CV_8U在编译时被替换成了0,就相当于实际执行时是在执行if(type == 0)的语句
CV_8U并不是一个像int这样的类型名,就是一个数字,看源码知道CV_8U这个就是一个自定义的int型的flag标志,只是人为得给这个变量赋予表示某个数据类型的意思罢了。所以也可以执行int a = CV_8U+2的操作,答案就是2。
再举一个宏的例子
有这么一个DEFINE_BUILTIN_OP_IMPORTER(Conv)表示的函数,函数内容我并没有截取完:
图1
看到DEFINE_BUILTIN_OP_IMPORTER(Conv)会觉得很奇怪,它定义了一个函数但为什么会没有返回值类型。那么我们很容易猜到这就是一个宏,于是在vscode中,把鼠标移到DEFINE_BUILTIN_OP_IMPORTER(Conv)上面,我们就可以看到它被展开后的样子:
图2
DEFINE_BUILTIN_OP_IMPORTER(Conv)被展开后的样子如下图所示,带分号的就表示一个完整的语句(这是c++的语法)。而最后一行即
NodeImportResult importConv( IImporterContext* ctx, ::onnx::NodeProto const& node, std::vector& inputs)最后是以圆括号结尾,并没有分号,这就说明它后面对接的就是图1中的大括号{}。
所以这个宏展开后我们发现,它其实就是定义了一个importConv函数的声明,又调用了registerBuiltinOpImporter函数把这个东西注册进去,它才会认识。然后再去定义importConv函数具体的定义。importConv函数的定义就是图1中的大括号里的内容。
refer:C++中的 # 和 ##:常用于宏定义。