宏(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:
差点忘了还有两个玩意儿:
#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; //也就是#的作用为在参数两边添加引号,##作用是连接两个参数