WRITE IN FRONT
- 介绍:"謓泽"正在路上朝着"攻城狮"方向"前进四"
- 荣誉:2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评百大博主、华为云享专家、阿里云专家博主、掘金优秀创作者、全网粉丝量6w+、全网访问量100w+
- 本文章内容由 謓泽 原创 如需相关转载请提前告知博主 ⚠
- 个人主页:謓泽的博客
- 专栏系列:【C】系列
- Gitee:謓泽 (wsxsx) - Gitee.com⭐️
- 点赞+ 收藏⭐️+ 留言
目录
宏定义不带参数
优点
定义宏
说明
命名事项
字符串宏常量
practice[练习]
#undef
宏定义不带参数
说明:宏定义指令的 #define 用来定义一个标识符和一个字符串,我们可以以这个标识符来表示这个字符串,在程序当中每次遇到该标识符的时候就用来所定义的字符串来进行替换它。宏定义的作用相当于给指定的字符串起了一个别名。
不带参数的宏的定义方式如下(这也是我们经常用到的宏定义)
#define 宏名 字符串 //没有分号,说没有分号倒不如说最好不要加分号
这里说下原因吧:因为宏定义它并不是C语言的语句,所以不用加分号。
- 表示这是一条预处理命令。
- 宏名实际上就是一个标识符,必须要符合C语言当中标识符的语法规定的。
标识符的规则:字母、数字、下划线,不以数字开头,注意:关键字不能作为标识符!预定义标识符有define、printf、scanf 它们是可以作为标识符的。
- 字符可以是常数、表达式 以及 格式字符串符等。
#define Num 1000
说明:上述代码的作用就是该程序中用Mum来替代1000,在编译预处理的时候,每当代码在源程序中遇到Mum就自动的用1000来进行代替。
注意:宏名要简单且定义的明确,一般习惯会用大写字母来去表示,来区分和变量的区别。
优点
- 方便程序的修改,不用对整个程序进行修改,只需对宏定义上进行修改。
- 提高程序的运行效率,更加方便模块化。
定义宏
#define 机制包括了一个规则,允许把参数替换到文本当中去,这种实现操作通常被称之为是宏(macro) 或者是 定义宏(define macro)
带参数的宏定义方式如下格式↓
#define 宏名(参数表)字符串
那么光说是不行的,我们就用宏定义来实现两个数字的相加。代码示例如下
#define _CRT_SECURE_NO_WARNINGS 1 #define ADD(x,y) x+y #include
int main(void) { printf("相加的值:%d\n",ADD(5, 5)); return 0; } 运行结果
相加的值:10
上述代码的意思是我们先调用宏也就是宏调用,把宏里面的值传递给宏名当中的参数表,然后再传过去的参数表替换到字符串的文本当中去。
注意:宏的参数是先完成替换的,不是先计算然后再进行传参的。如下代码所示↓
#define _CRT_SECURE_NO_WARNINGS 1 #define S(x) x*x #include
int main(void) { printf("相加的值:%d\n",S(3+1)); return 0; } 我一开始的时候看到这个代码以为是16,4*4不就是16吗。实际上我想错了。
它的工作原理是这个样子的,这里3+1就是宏的参数,那么就会把3+1传递到宏的参数当中去。那么这个时候替换完成之后就是:3+1 * 3+1,这不就是7吗。没错(@^0^)
一句话总结:参数会经过任何的计算直接传入进去。
实际上我们想要得到4*4的一个结果实际上这也很容易,把字符串文本修改下即可。
#define S(x) (x)*(x)
当然这还是不够严谨,完美再加一个小括号再外面。
#define S(x) ((x)*(x))
()YYDS!那么这个概念性的东西就说到这里,具体还是要多上手打下代码去进行实践。
那么接下来我们再举出一个例子,看大家能不能做对。(╹ڡ╹ )
#define _CRT_SECURE_NO_WARNINGS 1 #include
#define M(x) (x)+(x) int main(void) { printf("%d ", 10 * M(2)); return 0; } 注意⇢上述这两个代码是不一样的仔细看看哟
#define _CRT_SECURE_NO_WARNINGS 1 #include
#define M(x) (x)+(x) int main(void) { int a = 2; printf("%d ", 10 * M(a)); return 0; } 注意⇢上述这两个代码是等价的,变量也是可以传入到参数表当中去的。
选出上述代码正确的值不能 一共四个选项如下↓
A:40
B:22
C:88
D:10
可能有些人会选择A这个选项,因为 10 * 2 = 20 然后,20+20 = 40,但实际上这是错误的和上面所犯的错误都是一模一样的。
printf("%d",10 * (2) + (2));
原型如上代码所示↑
那我们想要得到 40 的值就必须要加小括号。如下形式↓
#define M(x) ((x)+(x))
其实这也无非就是操作符的优先级大小,切记(✿◕‿◕✿)
说明
宏参数和#define的定义中可以出现其他的#define定义的变量。但是对于宏,是不能出现递归的。
当预处理搜索#define定义的符号的时候,字符串常量的内容并不被搜索。
在使用函数的时候我们需要注意它的数据类型,但是在宏当中我们是不需要注意的,想是整形就是整形想是浮点型就是浮点型。说明用宏在这里是更加灵活的只是处理简单问题上切记。
命名事项
相信有些小伙伴已经发现了这个函数的宏的使用语法和函数是非常类似滴。所以语言本身就会没办法帮我们区分二者的一些使用。那么我们平时写宏或者函数的时候的习惯是↓
- 宏明全部大写形式。
- 函数明不要全部大写,建议第一个字母大写。
字符串宏常量
#include
#define Name chenze int main(void) { printf("%s",Name); return 0; } (error)字符串没有带双引号编译器会直接报错✘
(correvt)正确写法是要在宏字符串带上双引号✔
#define Name "chenze"
小知识点⇢宏是可以用来充当注释的效果的这个我在接触宏的时候我都没有想到这个问题,那么现在我们用BSC充当C++的风格注释。大家可以尝试去试一下这里我就不再演示了(@^0^)
practice[练习]
那么经过上述的知识点相信各位已经熟悉的差不多了接下来我们来做一道题目来练习practice以下吧。
题目内容⇢用宏实现整形变量(a)和整形变量(b)把原来的值用宏实现清0并且打印原来(a,b)没有被宏清0之前的值。示例代码如下
#include
#define empty0(a,b) a = 0;b = 0; int main(void) { int a = 20; int b = 10; printf("before:%d %d\n", a, b); empty0(a, b); printf("after :%d %d\n", a, b); return 0; } 运行结果
before:20 10
after :0 0
✔说明⇢上述结果当中我们可以知道变量(a)和变量(b)通过宏被修改成为了0的值。
✔拓展⇢用do...while(0)语句结构可以在宏插入多条语句的结构因为有花括号{}在。
#undef
#undef 是为取消定义,用于移除一个宏的定义。
格式形式如下
#undef NAME
如果现在的一共名字需要被重新定义的话,那么旧名字就会被移除。
如下代码所示
#define _CRT_SECURE_NO_WARNINGS 1 #include
#define NUM 10 int main(void) { #undef NUM printf("num of:%d\n",NUM); } 运行结果⇥error(错误)
说明⇢上述代码原本是要打印NUM宏定义的值的,但是由于我们使用了#undef取消宏定义了。此时编译器就相当于未定义标识符NUM了说的简单点相当于不存在了,注:是在取消宏定义之后的语句当中的。
拓展知识点⇥宏可以在任意地方使用。
#include
int main(void) { printf("num of 1:%d\n", 10); #define M 20 printf("num of 2:%d\n", M); return 0; } 运行结果
num of 1:10 num of 2:20
说明⇢在上述代码当中可以证明宏在源文件的任何地方宏都可以定义。宏的作用范围:从定义出开始往后它都是有效的。