既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
max = MAX;
else
max = 0;
return 0;
}
![](https://img-blog.csdnimg.cn/direct/e523ac52ca9b4e728a7ee9cb61dbe616.png)
>
> **如果是加了分号的情况,等替换后,if和else之间就是2条语句,而没有大括号的时候,if后边只能有⼀条语句。这里会出现语法错误。**
>
>
>
## 3、#define定义宏
#define机制包括了⼀个规定,允许**把参数替换到文本中**,这种实现通常称为**宏(macro)或定义宏(definemacro)。**
下面是宏的申明方式:
#define name( parament-list ) stuff
>
> 其中的 **parament-list** 是⼀个**由逗号隔开的符号表**,它们可能出现在stuff中。
>
>
>
**注意:**
参数列表的左括号必须与name紧邻,如果两者之间有任何空白存在,参数列表就会被解释为stuff的⼀部分。
举例:
#define SQUARE( x ) x * x
这个宏接收⼀个参数 x .如果在上述声明之后,你把 **SQUARE( 5 );** 置于程序中,预处理器就会用
下面这个表达式**替换上面的表达式: 5 \* 5**
警告:
这个宏存在⼀个问题:
观察下面的代码段:
#include<stdio.h>
#define SQUARE( x ) x * x
int main()
{
int a = 5;
printf(“%d\n”, SQUARE(a + 1));
return 0;
}
![](https://img-blog.csdnimg.cn/direct/10d80b2b406d4fbd9d3e5a0f14db85ce.png)
乍⼀看,你可能觉得这段代码将打印36,事实上它将**打印11,为什么呢?**
替换文本时,**参数x被替换成a+1,**所以这条语句实际上变成了:
printf (“%d\n”,a + 1 * a + 1 );
这样就比较清晰了,由替换产生的表达式并没有按照预想的次序进行求值。
在宏定义上加上两个括号,这个问题便轻松的解决了:
#define SQUARE(x) (x) * (x)
![](https://img-blog.csdnimg.cn/direct/6102126586304924925d555eebab083c.png)
这样预处理之后就产生了预期的效果:
printf (“%d\n”,(a + 1) * (a + 1) );
**这里还有⼀个宏定义:**
#define DOUBLE(x) (x) + (x)
定义中我们使用了括号,想避免之前的问题,但是这个宏可能会出现新的错误。
#include<stdio.h>
#define DOUBLE(x) (x) + (x)
int main()
{
int a = 5;
printf(“%d\n”, 10 * DOUBLE(a));
return 0;
}
![](https://img-blog.csdnimg.cn/direct/8a058dfe7d3d4d53a4846489137d42b8.png)
这将打印什么值呢?看上去,好像打印100,但事实上打印的是55.
我们发现替换之后:
printf (“%d\n”,10 * (5) + (5));
乘法运算先于宏定义的加法,所以出现了 55 .
这个问题,的解决办法是在宏定义表达式两边加上⼀对括号就可以了。
#define DOUBLE( x) ( ( x ) + ( x ) )
![](https://img-blog.csdnimg.cn/direct/a37da77f2abd4331bef2e6b87b48e6e9.png)
**提示:**
**所以用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中的操作符或邻近操作符之间不可预料的相互作用。**
## 4、带有副作用的宏参数
当宏参数在宏的定义中出现超过⼀次的时候,如果参数带有副作用,那么你在使用这个宏的时候就可能出现危险,导致不可预测的后果。副作用就是表达式求值的时候出现的永久性效果。
例如:
x+1;//不带副作⽤
x++;//带有副作⽤
MAX宏可以证明具有副作用的参数所引起的问题。
#include<stdio.h>
#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
int main()
{
int x = 5;
int y = 8;
int z = MAX(x++, y++);
printf(“x=%d y=%d z=%d\n”, x, y, z);//输出的结果是什么?
return 0;
}
这里我们得知道预处理器处理之后的结果是什么:
z = ( (x++) > (y++) ? (x++) : (y++));
>
> 根据#define的替换原则,将z的表达式替换成 z = ( (x++) > (y++) ? (x++) : (y++));
>
>
> 先计算(x++)>(y++),根据**后置++的口诀,先使用再+1**,因此5 与 8 比较,5不大于8,因此执行y++语句,此时**x=6** y=9 ,然后执行y++,根据后置++口诀,先使用再+1,因此**把9赋值给z**,最终y+1,因此**y=10**
>
>
>
![](https://img-blog.csdnimg.cn/direct/a9dd1e4084334e7e98635b1b2731406c.png)
所以输出的结果是:**x=6 y=10 z=9**
## 5、宏替换的规则
在程序中扩展#define定义符号和宏时,需要涉及几个步骤。
>
> **1. 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换。
> 2. 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
> 3. 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程。**
>
>
>
**注意:**
>
> 1. 宏参数和#define定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。
> 2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。
>
>
>
## 6、宏和函数的对比
**宏**通常被应用于**执行简单的运算**。
比如在两个数中找出较大的⼀个时,写成下面的宏,更有优势⼀些。
#define MAX(a, b) ((a)>(b)?(a):(b))
那为什么不用函数来完成这个任务?
原因有⼆:
>
> 1. 用于调用函数和从函数返回的代码可能比实际执行这个小型计算⼯作所需要的时间更多。**所以宏比函数在程序的规模和速度方面更胜⼀筹。**
> 2. 更为重要的是函数的参数必须声明为特定的类型。所以函数只能在类型合适的表达式上使用。反之这个宏怎可以适用于整形、长整型、浮点型等可以用于 > 来比较的类型。**宏的参数是类型无关的。**
>
![img](https://img-blog.csdnimg.cn/img_convert/dee01aedd8af038c28541d8adf570568.png)
![img](https://img-blog.csdnimg.cn/img_convert/98a1a16d555a5172693bdbe0e0270a48.png)
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
5549712843)]
[外链图片转存中...(img-pZ3Qp4g9-1715549712844)]
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**