一,预处理指令
程序员所编写的代码不是标准的C代码,需要一段程序翻译成标准C代码,才能被编译器编译
翻译的过程叫做预处理,负责翻译的程序叫做预处理器,被翻译的语句叫做预处理指令,以#号开头的都是预处理指令
gcc -E code.c 直接显示预处理后的结果
gcc -E code.c -o code.i 生成预处理文件
二,预处理指令的分类
#include 导入头文件/头文件包含
#include <> 从系统指定路径查找并导入头文件
#include "" 先从当前路径查找并导入,找不到再从系统指定路径查找并导入头文件
gcc code.c -I path 编译时指定头文件的加载路径path,最先从该路径查找
可以通过设置环境变量来修改、增加系统指定头文件加载路径 ~/.bashrc 终端配置文件
#define 定义宏
宏常量:#define 宏名 常量值
#define MAX 100
其实本质上就是,在代码中出现了宏名的地方,在预处理时替换对应的常量值
优点:提高可拓展性,提高可读性,提高了安全性还可以用在case后当作常量
tap:一般宏名全部大写,末尾不要加分号
预定义好的宏:
__func__ 获取所在函数
__FILE__ 获取所在文件
__DATE__ 获取所处于的 月 日 年
__TIME__ 获取当前时间
__LINE__ 获取所在行数
宏函数:其实就是带参数的宏
#define 宏名(参数名) 替换的代码
宏函数不是真正的函数,不检查参数类型,没有传参,只有表达式计算的结果,没有返回值。
#define SUM(a,b) a+b
SUM(num1,num2);
替换的过程:
1,先把代码中使用到的宏函数的地方替换为宏函数后面的代码 a+b
2,再把宏函数代码中使用到的参数替换为调用者提供的数据 num1+num2
宏的二义性:
由于宏代码所处位置、参数位置、优先级问题,导致同一个宏函数有不同的可解释的结果
如何避免宏函数的二义性:
1,给每个参数加小括号,给整个式子加小括号
2,再使用宏时,不要提供带自变运算符的参数
tap:宏函数后面的代码不能直接换行,需要在每一行末通过续行符 \ 来换行
如果有多行代码也可用大括号保护函数
条件编译:
根据条件决定哪些代码是否参与最终的编译
版本控制:
#if 条件
#elif 条件
#else
#endif
头文件卫士:
防止头文件被 重复 包含
#ifndef 宏名
#define 宏名
#endif //宏名
宏名:头文件名全部大写,小数点用下划线代替
tap:头文件中必须加入头文件卫士
调试,判断:
#ifdef 宏名
如果宏名定义了,则处代码参与编译
#else
否则,此处代码参与编译
#endif
gcc code.c -D宏名
可以在编译时定义宏
定义打印调试信息宏函数,是否打印信息,取决于是否定义了DEBUG宏
#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__)
浅学C++(3)学习C语言(预处理指令)
最新推荐文章于 2024-05-07 23:38:51 发布