目录
1.宏的优缺点
(1)宏的使用
宏的概念: 将一个数据用一个标识符代替,源程序中的该标识符均用对应的数据来代替。如同代码一这样的。(标识符不可以用关键字)
代码一:此代码是C++代码(本文所有代码运行环境均为win10系统下的vs2019)
//代码一
#include "iostream"
using namespace std;
#define PI 3.14
int main() {
cout << "PI = " << PI << endl;//输出 PI = 3.14
}
<1>.宏常量
宏常量就是如同代码一那样将一个数据用一个标识符代替的操作。但有时如果定义宏的时候不够仔细,就会出现奇奇怪怪的错误。
代码二:宏定义时不要加分号。
//代码二
#include "iostream"
using namespace std;
//#define PI 3.14; 报错,定义宏不可以加分号,因为标识符后面的东西都会被默认是宏的一部分
int main() {
//cout << "PI = " << PI << endl;
}
<2>.宏函数
宏函数:利用宏来实现类似于函数的功能,如同代码三。
代码三:利用宏函数求和。
#include "iostream"
using namespace std;
#define SUM(a,b) a+b
int main() {
cout << "SUM(a,b) = " << SUM(5,10) << endl;//输出 SUM(a,b) = 15
}
貌似宏函数要方便很多,但其实宏函数中也是有坑的,当实现的功能比较复杂时,如果不小心,宏函数就会出错。如同代码四。
代码四:宏函数出错的情况。下面这个宏函数的本意是求两数的乘积。
//代码四
#include "iostream"
using namespace std;
#define PRODUCT(a,b) a*b
int main() {
cout << "PRODUCT(a,b) = " << PRODUCT(1+2,2+3) << endl;//输出 PRODUCT(a,b) = 8
}
上述代码是不是感觉很迷惑,正确结果不应该时15吗,为什么是8。
将传入的数据代入宏函数来算一下:PRODUCT(1+2,2+3) == 1+2 * 2+3 == 1+4+3 == 8。错误在于,宏函数只是将数据代入,而不会检查合理性。这个宏函数的正确写法应该如同代码五。
代码五:正确的求乘积宏函数:
//代码五
#include "iostream"
using namespace std;
#define PRODUCT(a,b) ((a)*(b))
int main() {
cout << "PRODUCT(a,b) = " << PRODUCT(1+2,2+3) << endl;//输出 PRODUCT(a,b) = 15
}
代码六:这段代码更可以体现宏的副作用,这是一个比较大小的宏函数。
//代码六
#include "iostream"
using namespace std;
#define MAX(a,b) ((a)>(b))?(a):(b)
int main() {
int a = 2;
int b = 1;
int ret = MAX(++a, b);
cout << "ret = " << ret << endl;//输出 ret = 4
}
这段代码本应该打印3,为什么却打印4?还是将数据代入宏函数计算一下:MAX(++a, b) == ((++a)>(b)) ? (++a):(b) == ((3)>(1)) ? (4) : (b) == 4。宏函数在比较时已经通过 ((++a)>(b)) 对a加1,在返回结果时 (++a):(b) 再次对a加1,才造成了这样的错误。
通过上述情况,可以发现宏函数其实还是较为麻烦的,仅仅一个乘积宏函数就需要带这么多括号,并且宏函数还具有副作用。所以在使用宏函数时,一定要仔细判断是否合理。
(2)宏的优点
1.增强代码复用性,减少冗余代码。
2.提高性能,提升代码运行效率。
(3)宏的缺点
1.宏不方便调试,很多错误无法在调试中发现。
2.会导致代码可读性差,可维护性差,容易误用。
3.没有安全的检查,具有副作用。
2.宏的替代技术
1.宏常量:用const定义常量来替代宏常量。
2.宏函数:使用内联函数来替代宏函数。(关于内联函数在我的C++初阶的文章中有提到过)