一、预处理内容
C语言的编译过程
预处理(-E生成.i)——>编译(-S 生成.s)——>汇编(-c生成.o)——>链接(.elf)
预处理内容
1、头文件展开
2、宏替换
3、条件编译
二、头文件展开——库文件展开
三、宏定义
定义常量 #define MAX 100
定义表达式
定义函数
1、替换逻辑 宏替换只做简单的替换,不检查语法,在预处理阶段进行
2、宏定义的使用 定义预定俗成 字母大写
优点:
1.定义常数时可以杜绝幻数(具体的数,不知道为啥是这些,可以用宏定义例如直接在程序中表现176表达不清楚 可以 #define high 176,),用一些自定义标识符去代替,提高代码可读性,方便修改数值
2.定义宏函数 对于一些小而频繁使用的函数功能用宏定义,本质就是一个宏,只在预处理阶段进行替换,不占用运行时的时间,减少了函数调用、返回、和系统为函数分配释放空间的过程(不绝对比它慢),用编译时间和内存空间换运行时间
缺点:简单替换,不做与语法检查,宏函数的定义中常使用do{}while(0)防止出现语法错误
3、内置宏函数 系统内置宏常用__***__表示,自定义时应避免,
__LINE__ 显示行号
__func__ 显示函数名
__DATE–显示日期
__TIME__显示时间
4、#和## #字符串化运算符 ## 并接运算符
1.不替换参数,只替换对应字符
2、将对应字符字符串化
3、把宏参数名和宏定义代码连接在一起,形成一个新的标识符(只能两个)
四、条件编译 按照给定条件编译代码(只影响编译,不影响运行)
1、常见宏定义
#define 定义一个预处理宏
#undef 取消宏的定义
#if 编译预处理中的条件命令,相当于C语法中的if语句
#ifdef 判断某个宏是否被定义,若已定义,执行随后的语句
#ifndef 与#ifdef相反,判断某个宏是否未被定义
#elif 若#if, #ifdef, #ifndef或前面的#elif条件不满足,则执行#elif之后的语句,相当于C语法中的else-if
#else 与#if, #ifdef, #ifndef对应, 若这些条件不满足,则执行#else之后的语句,相当于C语法中的else
#endif #if, #ifdef, #ifndef这些条件命令的结束标志.
defined 与#if, #elif配合使用,判断某个宏是否被定义
2、常见的条件编译的三种形式
(1) #if defined(或者是ifdef) <标识符(条件)>
// 程序段
#endif
(2) #if !defined(或者是ifndef) <标识符(条件)>
//程序段
//endif
(3) #if ()
//程序段1
#elif ()
//程序段2
…….
#else
//程序段n
#endif
应用:
1:注释代码
2、调试
3、避免头文件的重复包含
五、gcc -D
D选项是用来在使用gcc/g++编译的时候定义宏的。
gcc -DDEBUG -D 后面直接跟宏命,相当于定义这个宏,默认这个宏的内容是1
gcc -DNAME=Peter -D 后面跟 key=value 表示定义key这个宏,它的内容是value
常用场景
-DDEBUG 定义DEBUG宏,可能文件中有DEBUG宏部分的相关信息,用个DDEBUG来选择开启或关闭DEBUG
-Dprivate=public -Dprotected=public 通常用于测试环境,把private 与 protected全替换为public 的。这个还是很常用的,比如我们使用gtest去单元测试,直接测试目标类的成员函数,但是可能目标类的成员函数为了封装性,它可能是protected,所以我们使用这个宏把它全变成public。
gcc -D 选项_我喜欢雨天的清新的博客-CSDN博客https://blog.csdn.net/sdoyuxuan/article/details/85050553