c06.11

预处理指令:

​ 程序员所编写的代码并不能被真正的编译器编译,需要一段程序翻译一下
​ 翻译的过程叫做预处理,被翻译的代码叫做预处理指令,以#开头的都是预处理指令

查看预处理的结果:
    gcc -E code.c   把预处理的结果显示到屏幕上
    gcc -E code.c -o code.i 把预处理的结果存储到code.i文件中

预处理指令的分类:

​ #include 文件包含
​ #include <> 从系统指定的路径查找并导入头文件
​ #include "" 先从当前路径查找,如果找不到再从系统指定路径查找并导入头文件
​ 操作系统是通过设置环境变量来指定头文件的系统查找路径,还可以通过编译参数 -I /path
​ 环境变量的设置通过 系统配置文件设置 : ~/.bashrc

#define 定义宏

宏常量:

​ #define MAX 100

​ 优点:提高代码的可扩展性(方便批量修改)、提高安全性(常量)、提高代码可读性、可以用在case后面

​ 注意:一般宏名全部大写,末尾不要加分号。

​ 【函数名:小写+下划线、全局变量:首字母大写、局部变量:全部小写、指针变量:+p、数组:arr、字符串str】

预定义好的宏:

            __func__   获取函数名
            __FILE__   获取文件名
            __LINE__   获取当前行号
            __DATE__   获取当前日期
            __TIME__   获取当前时间

宏函数:其实就是带参数的宏
不是真正的函数,不检查参数类型、没有传参、没有返回值,只有计算的结果
#define sum(a,b) a+b
1、把代码使用的宏函数替换为 宏函数后面的代码
2、把宏函数代码中使用的参数替换为调用者提供的参数
注意:宏函数、宏常量不能换行,但是可以使用续行符 \ 也可以使用大括号保护代码

宏的二义性:

​ 由于宏代码所处的位置、参数不同可能导致宏有不同的功能,这种叫做宏的二义性
​ 如何避免:宏函数整体加小括号、每个参数都加小括号
​ 注意:使用宏函数时不要提供带自变运算符的变量作为参数
​ 注意:容易出选择题,例如:问哪个宏可能有二义性,问宏函数的结果

常见的笔试面试题:
    如果是普通类型,他们从功能上没有任意区别
#define INTP int*
    INTP p1,p2,p3;  //只有p1是指针,p2p3都是int类型变量

typedef int* INTP;
    INTP p1,p2,p3;  //p1p2p3都是指针变量

宏函数与普通函数的区别?

​ 它们是什么?
​ 宏函数:不是真正的函数,只是代码替换,用起来像函数而已
​ 函数: 是一段具有某项功能代码的集合,编译成二进制指令存储在代码段,有独立的命名空间、栈内存
​ 有什么不一样:

​ 函数: 返回值 类型检查 安全 入栈、出栈 速度慢 跳转

​ 宏函数:运算结果 通用 危险 替换 速度快 冗余
优缺点:

条件编译:

​ 根据条件决定了哪些代码是否参与最终的编译

版本控制: [#if 0 注释代码]   
    #if
    #elif
    #else
    #endif

头文件卫士:    防止头文件被重复包含
    #ifndef 宏名
    #define 宏名
    #endif//宏名

判断、调试:    -D宏名  在编译时添加宏
    #ifdef 宏名
    #else
    #endif

代码调试:
#ifdef DEBUG
    #define debug(...) printf(__VA_ARGS__)
#else
    #define debug(...)
#endif

#define error(...) printf("%s:%s:%d %s %m %s %s\n",__FILE__,__func__,__LINE__,__VA_ARGS__,__DATE__,__TIME__)

作业:
    实现一个交换两个变量的宏函数,能写多少种?哪种最通用
    swap(a,b)

常考的笔试面试题:

​ 定义一个宏 表示100年有多少秒,忽略闰年问题
​ #define YEAR_SEC (360024365*100u)

在类型重定义时 #define 与 typedef的区别?

宏函数与普通函数的区别?
posted @ 2021-06-16 17:17  de06  阅读(89)  评论(0)    收藏  举报