C++宏的总结

1,宏和函数拥有以下几点区别
1)宏是简单的符号替换,不会检查参数类型,而函数会严格检查输入的参数类型。
2)因为宏是在编译期进行的符号替换,所以在运行时,不会带来额外的时间和空间开销,而函数会在运行时执行压栈出栈的操作,存在函数调用的开销。
3)宏是不可以调试的,而函数可以进行单步调试。
4)宏不支持递归,函数支持递归。

2,如果宏的内容很长,很多,那么可以写成多行,每行的末尾添加\,以表明后面的一行依然是宏的内容。
3,如果想要取消对一个宏的定义,可以使用#undef预处理指令,比如要取消之前定义的ADD宏,只要像下面即可:
#undef ADD
4,宏定义中常见的 do{ }while(0)
在阅读第三方源码时,经常见到宏定义中有一个do{ }while(0)语句,这是为什么呢?比如我们定义一个交换两个值的宏

#define swapint(x, y) int tmp = x; x = y; y = tmp;
在大部分情况下可以工作,但是如果之前已经定义了tmp这个变量,则就会出错了,那我们可以把tmp换成平时不常用的名字,就大大降低了重名的概率了,这确实是一个办法,但不完美,因为即使这样,依然无法用在switch语句中。
int x = 1, y = 2;
switch (value)
{
    
    
    case 1:
        // 编译出错,因为case语句中不允许声明变量
        swapint(x, y);
        break;
}

那我们想,是否可以定义宏的时候,加上一层大括号,嗯,确实可以。

#define swapint(x, y) {
      
      int tmp = x; x = y; y = tmp;}

这样便可以用在switch语句中了。是否就完美了呢,依然不行,因为还可能会影响if语句的执行,看下面的例子:

int x = 1, y = 2;
if (x < y)
    swapint(x, y);
else
    someaction();
// 上面的代码展开
if (x < y)
    {
    
    int tmp = x; x = y; y = tmp;};
else
    someaction();
// 编译出错,因为在else之前多了一个分号,导致语法错误,那么能不能不加分号
// 可以,但是C++程序员一般都习惯在末尾添加分号,而且不过不加分号,也会影响
// IDE的自动代码格式化

这时,就要祭出do{ }while(0)大杀器了,使用do{….}while(0) 把它包裹起来,成为一个独立的语法单元,从而不会与上下文发生混淆。同时因为绝大多数的编译器都能够识别do{…}while(0)这种无用的循环并进行优化,所以使用这种方法也不会导致程序的性能降低。

猜你喜欢

转载自blog.csdn.net/xiaoan08133192/article/details/121907425
今日推荐