定义宏可以说是每个敲代码敲得多的人必然需要学习的一项新技能。
毕竟代码里有很多地方是重叠的,如果能把这些地方简短地表示出来可以大大缩减工作量。
比如博主打ACM的时候就特别喜欢定义这么一个宏
#define rep(i, x, y) for(int i= x; i < y; i++)
这样子一来,for循环少了80%,变成了简短的rep,可以说是非常爽了。
你有没有想过?宏比你想的有意思得多。
事先说明,博主全文的代码均使用GCC 4.9.2编译。
文章目录
#define true false
#include <bits/stdc++.h>
#define true false
using namespace std;
int main()
{
if(true) printf("hello, world\n");
}
一个简短的实验代码,最终的结果大家猜到了吗?
接下来揭晓答案:
可以看到,那行printf并没有执行,换而言之,代码中的true确实被赋了一个false值。
#define true false + #define false true
在经过刚才那个想法后,很多人可能想尝试把这两个宏一起定义一遍。这样的结果是什么呢?
#include <bits/stdc++.h>
#define true false
#define false true
using namespace std;
int main()
{
if(true) printf("hello, world\n");
if(false) printf("goodbye, world\n");
}
这一回的运行结果是什么呢?是都打印出来?是循环定义报错?
揭晓答案:
大跌眼镜吧。不管是true还是false,都还是原来的值。
即便你把两个#define反过来,运行结果依然不变,也就是说true和false依然保持原值。
至于具体为什么,大家接着往下看就明白了。
#define true false + #define false 1
#include <bits/stdc++.h>
#define true false
#define false 1
using namespace std;
int main()
{
if(true) printf("hello, world\n");
if(false) printf("goodbye, world\n");
}
还是无奖竞猜,大家想想这一回会输出什么?是和上一种情况一样吗?
揭晓答案
true的值没有变动,但是false的值却被设为了1。此外这次把两个#define返回来运行结果还是不变。
#define false true + #define true 0
这个其实跟刚才差不多,那为什么还要放出来呢?是因为我放出来这个,可能有些同学就知道刚才那一系列运行结果的原因了。
#define false true
#define true 0
using namespace std;
int main()
{
if(true) printf("hello, world\n");
if(false) printf("goodbye, world\n");
}
运行结果如下::
false的值没有变动,但是true的值被设为了0.
#define true false + #define cond true
这一回是先修改了true的值,在把其他变量定义为true
#include <bits/stdc++.h>
#define true false
#define cond true
using namespace std;
int main()
{
if(true) printf("hello, world\n");
if(cond) printf("goodbye, world\n");
}
运行结果如下图所示
可以看到,true确实被修改了,而且再把它赋给其他变量的时候也确实是新值false。
#define a 1 + #define b a + # define a 2
这一回就没有true和false了,而是帮助大家理解#define原理的一串代码
#include <bits/stdc++.h>
#define a 1
#define b a
#define a 2
using namespace std;
int main()
{
printf("%d %d\n", a, b);
}
运行结果:
#define a 1 + #define a 2
这一回我们不再全部放在代码开头,而是要把两个define分开放,也就是:
#include <bits/stdc++.h>
#define a 1
using namespace std;
int main()
{
printf("%d\n", a);
#define a 2
printf("%d\n", a);
}
分开后的运行是先两个都运行还是先后运行呢?
#define 1 2
刚刚大家可能渐渐有眉目了,最后给大家这么个宏,大家猜猜运行结果是什么?
#include <bits/stdc++.h>
#define 1 2
using namespace std;
int main()
{
printf("%d\n", 1+1);
}
运行结果:
报错了,内容如下(简单来说,就是要求标识符不能是数字)
#define 究竟做了什么?(全CSDN最详细讲解)
从之前的几个例子中,很多同学已经得到答案了。那么,我现在就公布实际的情况。
#define 的函数原型为
#define 标识符 值
- #define 定义完一个宏后相当于生成了一个字典,在又遇到字典当中键的时候,自动换成键对应的值
- 虽然加#的操作都叫预操作,但是实际上#define定义宏是随着代码向下执行的时候定义的。define a 1 + #define a 2例子中a从1变成2说明了这一点。
- #define是可以传递的,而且是动态链接,即把标识符b链接到标识符a后,修改a,b的值也会变(换言之,b就是a的一个浅复制,直接指向a)
- 标识符必须是变量(true和false是一个已经预定义好的宏,所以不会报错)
- 当#define用其他标识符定义另一个标识符时,发现字典中存在自环的时候,比如
#define x y+1
#define y 2*x
这时就会出现循环定义,x寻找y,y寻找x…为了保护代码,就会阻止定义,这就是为什么#define true false + #define false true 会什么都没变。