> 文档中心 > 宏相关的细节讲解。

宏相关的细节讲解。

今天继续预处理相关知识讲解。

今天也要开心哦!
在这里插入图片描述

宏和函数对比

宏:

  1. 代码长度:每次使用时,宏代码都会被插入到程序中。除了非常
    小的宏之外,程序的长度会大幅度增长
  2. 执行速度:更快
  3. 操作符优先级:宏参数的求值是在所有周围表达式的上下文环境里,除非加上括号,否则邻近操作符的优先级可能会产生不可预料的后果,所以建议宏在书写的时候多些括号。
  4. 带有副作用的参数:参数可能被替换到宏体中的多个位置,所以带有副作
    用的参数求值可能会产生不可预料的结果。
  5. 参数类型 :宏的参数与类型无关,只要对参数的操作是合法的,
    它就可以使用于任何参数类型
  6. 调试 :宏不方便调试。
  7. 递归 :宏不能递归。

**函数 **

  1. 代码长度:函数代码只出现于一个地方;每次使用这个函数时,都调用那个地方的同一份代码
  2. 执行速度:存在函数的调用和返回的额外开销,所以相对慢一些
  3. 操作符优先级:函数参数只在函数调用的时候求值一次,它的结果值传递给函数。表达式的求值结果更容易预测
  4. 带有副作用的参数:函数参数只在传参的时候求值一次,结果更容易控制。
  5. 参数类型 :函数的参数是与类型有关的,如果参数的类型不同,就需要不同的函数,即使他们执行的任务是不同的。
  6. 调试 :函数是可以逐语句调试的
  7. 递归 :函数是可以递归的
    函数和宏都各有优缺点,使用是分情况讨论

条件编译

单分支
#if //常量表达式
#endif//表达式由预处理求值。
看个例子:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
这里可以看出,如果#if后面是0时候,可以看出打印的代码变灰色,表示不能执行这条代码。是非0则正常执行,这是条件编译一种但是必须要#if 常量表达式和#endif 联合使用才可以。

多分支:
#if 常量表达式
#elif 常量表达式
#else
#endif

看个例子:
大家可以分析下逻辑

#define NUM 3int main(){#if NUM == 1printf("胡杨\n");#elif NUM == 2printf("树下\n");#elif NUM == 3printf("胡杨树下\n");#else printf("haha\n");#endif return 0;}

在这里插入图片描述
这是多分支条件,最后只会执行一条语句,其他的直接在预编译时被替换了。

判断宏是否定义
有下列两种做法:

#define MAX 1int main(){#if defined(MAX)printf("1.已定义\n");#endif#ifdef MAXprintf("2.已定义\n");#endifreturn 0;}

在这里插入图片描述
这两种判断宏定义的办法都可以。

空内容的宏和已定义的宏区别
看个例子:

#define MAXint main(){#ifdef MAXprintf("已定义\n");#endifreturn 0;}

这里会输出已定义吗?
这是会输出的,因为定义了,只不过是空内容。

文件包含

#include “test.h”(自己创建的)
查找策略:先在源文件所在目录下查找,如果该头文件未找到,编译器就像查找库函数头文件一样在标准位置查找头文件。如果找不到就提示编译错误。

#include (库里面的)
查找头文件直接去标准路径下去查找,如果找不到就提示编译错误。

那么库中的头文件可以用 “” 引用吗?
首先是可以的,但是不推荐,但是这样做查找的效率就低些,当然这样也不容易区分是库文件还是本地文件了。

如何避免头文件重复包含的呢?
首先我们,要明白,每一次包含一个头文件,就会使程序内容大一点,会拖慢点效率,那么怎么解决呢?
1.使用条件编译。(不推荐)
在每个头文件的开头写上

#ifndef TEST_H
#define TEST_H
//头文件的内容
#endif //TEST_H

2.使用#pragma once
用#pragma once就可以避免头文件重复包含了。

下期预告:

还有一些预处理指令,
比如修改结构体默认对齐数等的没有讲,
留到下期讲解吧。下期更精彩哦~~~
在这里插入图片描述