1.不带参数的宏(一般的使用)
#define 宏名 宏定义字符串
其含义为定义一个名为“宏名”的宏,并将该宏与其名字后的第一个空格后知道改行结束的所有字符串等价起来。然后将这个字符串替换随后程序中任何位置出现的宏名。
2.带参数的宏
#define 宏名(参数1,参数2,… ,参数n) 宏定义字符串
该语句定义了一个名为宏名的宏,该宏接收一组参数,在随后的程序中任何出现宏名的地方,预处理器将使用后面的宏定义字符串替换该宏名,并将使用实际的参数替换宏定义字符串中的参数。
注意:
带参数的宏与函数的区别:
① 带参数的宏的参数列表中的参数没有数据类型,仅是一个名字,对应宏定义字符串中的参数
② 要注意使用括号,来避免宏展开时可能出现的问题,如:
#include <iostream>
using namespace std;
//这个地方必须要加括号,否则程序不识别
#define MAX(A,B) (A>B?A:B)
int main(){
cout << MAX(1,10) << endl;
cout << MAX(100.32,10.9) << endl;
cout << MAX(1,-1) << endl;
cout << (1>10?1:10) << endl;
return 0;
}
③ 带参数的宏的使用类似于函数调用,要注意如果实参是表达式的话容易出问题,如:
#include <iostream>
#include <cstdio>
using namespace std;
#define S(r) r*r
int main(){
int area = S(1+1);
cout << area << endl;
return 0;
}
程序运行结果为3。
原因如下:
··#define S(r) r*r
area=S(a+b);
替换过程为:第一步换为area=r*r;,第二步被换为area=a+b*a+b;
因此S(1+1) r*r 1+1*1+1 ,由于运算符优先级的关系,最终计算结果为3。
正确的宏定义是#define S(r) (r)*(r) 用括号限定运算符优先级。
④ 宏名和参数的括号间不能有空格。
⑤ 宏的虚实结合不存在类型,也没有类型转换,宏定义时其参数没有类型可言,只是单纯的名字字符串。
⑥ 宏替换在编译前进行,不分配内存,宏的展开不占运行时间,只占编译时间。
⑦ 由于宏类似于函数调用,又具有其独特的方便性,所以使用恰当的话可以大大的减少程序的代码量。如下面的一个穷举问题,定义一个宏作为for循环,然后嵌套使用即可,不用每一次再写for语句或是拷贝、粘贴导致容易出错。
//采用带参数的宏让程序编写更加简单
#include <iostream>
using namespace std;
#define FOR(A) for(A=1;A<=9;A++)
int main(){
int a,b,c,d,e;
a=b=c=d=e=1;
int n,m,cnt = 0;
//巧妙的利用for语句的使用形式,从而可以使用带参数的宏
FOR(a)
FOR(b) if(b!=a)
FOR(c) if(c!=b&&c!=a)
FOR(d) if(d!=c&&d!=b&&d!=a)
FOR(e) if(e!=d&&e!=c&&e!=b&&e!=a){
n = (a*10+b) * (c*100+d*10+e);
m = (a*100+d*10+b) * (c*10+e);
if(m==n) ++cnt;
}
cout << cnt << endl;
return 0;
}