前面认识了#include
指令,接着来看#define
指令,它可以实现宏定义。宏是啥意思?
把参数批量替换到文本中,这种实现通常称为宏(macro)或定义宏 (define macro)
可以通过#define
来定义宏,规则如下:
#define 宏名(记号) 内容
比如现在想通过宏定义一个PI:
#define PI 3.1415926
这样就可以了,那么怎么去使用它呢?
#include <stdio.h>
#define PI 3.1415926
int main() {
// 就像使用变量一样,我们可以直接将PI放到这个位置
printf("π的值为:%f", PI);
}
π的值为:3.141593
在编译时,预处理程序会进行宏替换操作,也就是将程序中所有的PI
全部替换为3.1415926
,注意这个跟类型无关,是赤裸裸的纯文本替换,也就是相当于把代码修改了,PI那里直接变成3.1415926
,当然如果你定义为其他任意的内容,同样会替换到那个位置,但是至于替换之后程序还正不正常就不知道了。
通过下面这个例子来加深对文本替换这句话的理解:
#include <stdio.h>
#define M a + b
int main() {
int a = 10, b = 20;
printf("%d", M * a);
}
210
如果按照一般思维,M 是 a + b,那么替换上去之后应该就是 30,然后 30 x 10 最后得到的应该是 300 才对。
怎么会算出来是 210 的呢?
实际上在编译时仅仅是做了文本替换,相当于最后的代码是:
printf("%d", a + b * a);
最后结果就是 210 了。
当然任何地方都可以使用宏替换,包括类型,反正最后都会变成被替换的内容:
#define lbwnb long
int main() {
lbwnb a = 10L;
}
当然除了这种简单的替换之外还可以添加参数,就像函数那样:
#include <stdio.h>
#define MUL(x) x * x
int main() {
printf("%d", MUL(9));
}
81
虽然这里搞得像函数一样,但是最后还是会被替换为 x * x,而这个 x 就是填写的参数,所以最后会变成 9 * 9 替换上去,程序运行出来的结果就是 81 了。
直接调函数肯定也是没问题的,反正就纯替换:
#include <stdio.h>
#define bb(i) printf("我是宏替换的:%d", i);
int main() {
bb(666);
}
我是宏替换的:666
那要是想在字符串里面加一个宏定义中的参数呢?
#include <stdio.h>
// 使用#直接在字符串中进行宏替换,否则默认情况下会被当做一个字符
#define bb(str) printf("我是宏替换的:" #str " <");
int main() {
bb("替换成功");
}
我是宏替换的:"替换成功" <
当然还可以替换宏中的部分:
// ##会使用参数进行拼接
#define TEST(n) x##n
int main() {
// 这里传入1,那么实际上就是被替换为x1
int TEST(1) = 10;
// 所以上面其实是int x1 = 10
x1 = 20;
}
宏既然可以定义出来,那么也可以取消定义,可以使用#undef
来取消已有的宏定义:
可以看到在使用#undef
之后,直接不认识了。
当然除了我们自己可以去定义之外,系统也为我们提供了一些预定义的宏:
宏名称 | 含义 |
---|---|
_ _ DATE _ _ | 当前的日期,格式为类似 Jun 27 2023 的字符串 |
_ _ TIME _ _ | 当前的时间,格式为类似 10:23:12 的字符串 |
_ _ FILE _ _ | 当前源代码文件的名称(含路径)的字符串 |
_ _ LINE _ _ | 当前所处的行号是多少就替换为多少,整数 |
这里只列出了一部分。
环境:
- GCC 11.4.0
- VSCode 1.93.1