预处理指令
在文件翻译成0和1之前做的操作我们称之为预处理指令
一般情况预处理指令都是以#号开头
预处理指令分为宏定义、条件编译、文件包含
宏定义
宏定义的作用
会在程序翻译成0和1之前,将所有宏名替换为宏的值
宏名定义规范
- 定义宏名使用 #define 宏名 进行定义,宏名尾部不需要用分号结尾
- 定义宏名的2种方式:
- 1.宏名使用大写字母,多个单词用下划线隔开。例如:#define COUNT
- 2.宏名使用k开头,多个单词直接使用驼峰命名。例如:#define kClassCount
注意: 宏定义不要以分号结尾
宏定义的作用域
- 从定义的那一行开始,一直到文件末尾
- 虽然默认情况下宏定义的作用域是从定义的那一行开始,一直到文件末尾,但是我们也可以通过对应的关键字undef提前结束宏定义的作用域
宏定义的使用场景
- 我们的app需要频繁的于api进行交互获取数据进行展示,不同页面调用api的路由不同,但是域名是相同的,此时可以将域名定义为宏
#include <stdio.h>
// 定义宏变量API_DOMAIN
#define API_DOMAIN "http://api.api.com"
int main(int argc, const char * argv[]) {
char loginApi[] = API_DOMAIN"/login"; // 使用宏定义
printf("loginApi --> %s\n", loginApi); // loginApi --> http://api.api.com/login
return 0;
}
- 获取手机屏幕的宽度
- 获取手机系统版本号
个人理解: 宏定义其实就是类似于其它语言中的常量定义
不带参数和带参数的宏定义
- 不带参数的宏定义
#include <stdio.h>
// 定义宏变量API_DOMAIN
#define API_DOMAIN "http://api.api.com"
int main(int argc, const char * argv[]) {
char loginApi[] = API_DOMAIN"/login"; // 使用宏定义
printf("loginApi --> %s\n", loginApi); // loginApi --> http://api.api.com/login
return 0;
}
- 带参数的宏定义
#include <stdio.h>
// 宏定义不会做任何运算,只是一个简单的替换
#define API_DOMAIN2(route) "http://api.api.com"route
int main(int argc, const char * argv[]) {
char loginApi[] = API_DOMAIN2("/login");
printf("loginApi --> %s\n", loginApi); // loginApi --> http://api.api.com/login
return 0;
}
条件编译
条件编译使用关键字#if、#ifdef、#ifndef
- #if 用于判断表达式
#define COUNT 10
#if COUNT == 10
printf("COUNT == 10");
#elif COUNT == 20
printf("COUNT == 20");
#else
printf("COUNT 值异常");
#endif
- #ifdef 用于判断宏变量是否定义
#define COUNT 10
// 判断宏变量COUNT是否定义
#ifdef COUNT
printf("COUNT被定义");
#else
printf("COUNT未定义");
#endif
- #ifndef 用于判断宏变量是否未定义
// 判断宏变量COUNT是否未定义
#ifndef COUNT
printf("COUNT未被定义");
#else
printf("COUNT定义");
#endif
条件编译会对给定的条件进行判断,如果条件满足就编译条件后面的内容,与if条件判断类似
条件编译不能用来判断变量,因为不在同一声明周期
一般情况下,条件编译是和宏定义结合在一起使用的
#include <stdio.h>
#define DEBUG 0 // 0表示调试阶段,1表示发布阶段
#if DEBUG == 0
#define NJLog(format, ...) printf(format, ## __VA_ARGS__)
#elif DEBUG == 1
#define NJLog(format, ...)
#endif
int main(int argc, const char * argv[]) {
int i = 10;
// 当DEBUG等于0的时候,会将 NJLog("i --> %i\n", i) 替换为 printf("i --> %i\n", i)
NJLog("i --> %i\n", i); // i --> 10
return 0;
}
条件编译和if的区别
共同点:
- 都可以对给定的条件进行判断
- 添加满足或者不满足都可以执行特定的代码
- 可以执行多个表达式
不同点:
- 生命周期不同,if 是运行时,#if 是在编译之前
- #if 需要一个明确的结束符号 #endif。如果省略掉#endif,那么系统就不知道条件编译的范围,那么会满足条件之后的第二个条件之后的所有内容都清除掉
- if 会将所有的代码都编译到二进制中,#if 只会将满足条件的代码块编译到二进制中
#if 的优点
- 缩小应用程序的大小
文件包含
文件包含使用 #include 指令
详情参考:https://blog.youkuaiyun.com/crazy_zhangcong/article/details/87939292