关于宏的一些知识

宏(macro)本质上是文本替换,也就是在预编译的时候,会把对应的宏(常量or函数)展开替换。

而宏根据有无参数有不同的写法

[1]无参数(对象宏)

#include <iostream>
#define PI 3.14

int main(void)
{
    std::cout << PI << std::endl;
}

//预编译之后为 std::cout << 3,14 << std::endl

[2]有参数(函数宏)

#include <iostream>

#define MIN(x,y) ((x) > (y) ? y : x)
using namespace std;
int main(void)
{
    cout << MIN(5,3) << endl;
}
//预编译之后,就会变成 ((x) > (y)? y: x)

注:这里里里外外加了好几层括号,是为了防止一些特殊状况的发生,比如在MIN(X, Y)前乘以某个数,由于宏本质上是文本展开,因此如果不加括号会导致一些运算顺序上的问题。

有参数的宏还有一种情况,就是函数体比较大,一行写不下的情况,这个时候就需要用到符号"\"了

#include <iostream>
using namespace std;

#define RETURN_MAX(x, y, z)   \
            {   
                int max = x;            \
                if (y > x)  max = y;  \
                if (z > x)  max = z;   \
            }

int main(void)
{
    cout << MAX(5, 6, 7) <<endl;
}
//这样子预编译的时候就会自动替换上函数体了

作为补充:我们经常会看到在宏函数定义中出现do { ...... } while(0)语句,这里Robert Love给出了解答:

do{...}while(0)在C中是唯一的构造程序,让你定义的宏总是以相同的方式工作,这样不管怎么使用宏(尤其在没有用大括号包围调用宏的语句),宏后面的分号也是相同的效果

详细的就不展开讲了,这里贴两个写得比较好的blog:

宏定义的黑魔法 - 宏菜鸟起飞手册

do{......} while(0)在宏定义中的作用

 

差点忘了还有两个玩意儿:

#include <iostream>
using namespace std;

#define  STRING(x) #x
#define  PRINT(x, y) x##y
int main(void)
{
    cout << STRING(what the fuck) << endl;
    cout << PRINT("go", "hell") << endl;
}

//预编译之后,就变成了cout << "what the fuck" << endl
//以及 cout << ”go hell" << endl;
//也就是#的作用为在参数两边添加引号,##作用是连接两个参数

 

posted @ 2019-07-31 15:35  jckcoenf  阅读(393)  评论(0编辑  收藏  举报