注:部分来源于网络相关资料,用于个人总结学习记录,如有侵权,请联删。
1、编译、连接处理过程
![](https://i-blog.csdnimg.cn/blog_migrate/33616b9a0f6af47211c8eb792d4d8964.png)
预处理命令不是c++本身的组成部分,更不是c++语句,它是c++标准规定的可以出现在c++源程序文件中的命令。
这些命令必须以#开头,结尾不加分号,可以放置在源程序中的任何位置,其有效范围是从出现位置开始到源程序文件末尾。
2、宏定义
在c++程序中允许用一个标识符代表一个字符文本,称为宏,标识符为宏明
宏是由宏定义事先定义的。预处理时,对程序中所有后续的宏名实例(称为宏引用),预处理器都用字符文本去替换,称为宏替换
(1)不带参数的宏定义
不带参数的宏定义的命令形式为:
#define 宏名 字符文本
![](https://i-blog.csdnimg.cn/blog_migrate/2d5abe20b11eab3cd29f43e431b16e6f.png)
宏定义只是简单置换,不作语法检查,因此,宏串中的每个字符都是有效字符
(2)带参数的宏定义
带参数的宏定义的命令形式为:
#define 宏名(参数表) 字符文本
带参数的宏的引用形式为:
宏名(引用参数表)
例如:
![](https://i-blog.csdnimg.cn/blog_migrate/bda9a6ef06b1e3ae0e71b3a5cb1e142e.png)
(3)#和##预处理运算
#运算符的作用是文本参数“字符串化”,即出现在宏定义字符文本中的#把跟在后面的参数转换成一个c++字符串常量。
![](https://i-blog.csdnimg.cn/blog_migrate/60b47e36ed36b7c559dea6f15a913978.png)
本来就是字符串形式,那么就不会再添加双引号了
##运算符的作用是将两个字符文本连接成一个字符文本,如果其中一个字符文本是宏定义的参数,连接会在参数替换后发生。
![](https://i-blog.csdnimg.cn/blog_migrate/dd9b03acba0c63972913edf7b09ac78e.png)
##就是个粘合剂,将前后两部分粘合起来,也就是有“字符化”的意思。但是“##”不能随意粘合任意字符,必须是合法的C语言标示符。在单一的宏定义中,最多可以出现一次“#”或“##”预处理操作符。如果没有指定与“#”或“##”预处理操作符相关的计算次序,则会产生问题。为避免该问题,在单一的宏定义中只能使用其中一种操作符(即,一份“#”或一个“##”,或都不用)。除非非常有必要,否则尽量不要使用“#”和“##”。
3、文件包含
文件包含命令的作用是指定的文件插入到该命令所处的位置上取代该命令,然后再进行编译处理,相当于将文件的内容嵌入到当前的源文件一起编译。
文件包含命令为#include,有两种命令形式:
第一种形式:
#include <头文件名>
第二种形式:
#include "头文件名"
(1)文件包含路径
文件包含命令中的头文件可以写成绝对路径的形式,例如:
![](https://i-blog.csdnimg.cn/blog_migrate/b1e87cca642b84d51717d9f1a709c511.png)
文件名也可以写成相对路径的形式:
![](https://i-blog.csdnimg.cn/blog_migrate/ef97e0f8e0a748839a2c260dd4799228.png)
<>表示只到系统默认路径里面去找," "表示先去用户路径找,然后再去系统默认路径去找。
(2)文件包含的重复包含
头文件有时需要避免重复包含,例如一些特定声明不能多次声明,而且重复包含增加编译时间。这是可以采用以下两个办法之一:
使用条件编译
使用特殊预处理命令#pragma
4、条件编译
条件编译就是专门用来解决头文件重复包含的问题的
(1)#ifdef
测试条件字段是否定义,以选择参与编译的程序代码段,有两种命令形式:
1)第一种形式
![](https://i-blog.csdnimg.cn/blog_migrate/e73e6f8c06dedc2d400c7c8ea01934b5.png)
2)第二种形式
![](https://i-blog.csdnimg.cn/blog_migrate/36fd142117d708da64a8c630ea2e0f50.png)
(2)#if 条件编译命令
根据表达式的值来选择参与编译的程序代码,其命令形式为:
![](https://i-blog.csdnimg.cn/blog_migrate/71ab27fc60db9a1d89d58372d4e9c62b.png)
也可以使用嵌套的#if条件编译命令#if--#elif,命令形式为:
![](https://i-blog.csdnimg.cn/blog_migrate/b00f611c93d291fc2e4a2e671e2bbb4c.png)
32位操作系统与64位操作系统需要编译和使用的代码是不一样的,所以区分不同的编译系统也是条件编译的使用之一。
实例:
我们在添加打印信息时会自定义打印log的方式,如下:
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "HUA"
#undef ALOGE
#undef ALOGD
#undef ALOGI
#include <android/log.h>
#define ALOGE(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define ALOGD(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)