文章目录
宏
宏(macro)其实就是一个特定的字符串,用来直接替换。 在预处理阶段就会被替换。
- 使得程序的可读取有所提高,使用一个又有意义的单词来表示一个无意义数字(某个值)
- 方便对代码进行迭代更新, 如果代码中有多处使用到该值, 则只需要修改一处即可(定义)
- 提高程序的执行效率,可以使用宏来实现一个比较简单的操作。用来替代函数的调用-有点儿类似内联函数。
使用:
1.无参宏
意味着我们在使用该宏的时候不需要携带额外的参数 。其实就是定义常量
c
#define PI 3.14 //定义常量
int main(int argc, char const *argv[])
{
printf("%f\n" , PI );
return 0;
}
2.有参宏
c
#include <stdio.h>
//定义有参数宏
#define MAX(a,b) a>b?a:b
int main(int argc, char const *argv[])
{
int a=1,b=2;
int c=3,d=5;
printf("%d\n", MAX(a,b));
printf("%d\n", MAX(c,d));
}
宏只是直接文本替换,没有任何的判断以及语法检查的操作甚至运算
宏在编译的第一个阶段(预处理), 被处理完成,运行的过程中不占用时间(宏已经不存在)宏在预处理的时候直接展开。
-
有参宏: 只是文本替换,复杂的运算在里面可能出现问题。
-
宏只能写在同一行中(逻辑行),如果迫不得已需要使用多行来写一个宏则可以使用转义字符\把换行符转义掉
条件编译
在C语言中,程序员可以根据不同的条件,有选择性地编译不同的代码块(忽略其它的代码块),从而产生不同的目标文件,这种机制称为条件编译。
借助条件编译,我们可以在同一份源代码中包含针对不同操作系统、硬件架构或功能配置的代码,而无需维护多个独立的源文件。
条件编译是预处理器的功能,不是编译器的功能。条件编译通过以#开头的预处理命令来完成,包括 #if、#elif、#else、#endif、#ifdef和 #ifndef。
无值宏
代码定义宏或者通过命令行结尾加-D or -U
c
#define DEV_MODE //是否是开发模式
int main(int argc, char const *argv[])
{
#ifdef DEV_MODE
printf("开发大佬");
#endif
#ifndef DEV_MODE
printf("不是开发大佬");
#endif
return 0;
}
有值宏:
预处理器在处理 #if 时:只能识别整数常量(integer constants)支持整数、字符常量(字符会转换为 ASCII 值)不支持字符串比较
c
#include <stdio.h>
#define DEV_MODE01 1 //true
#define DEV_MODE02 0 //fasle
#define DEV_MODE03 3 //true
#define DEV_MODE04 'A' //true
#define DEV_MODE05 "true" //不能这样定义,只能识别整数常量,没法判断是true还是false
int main(int argc, char const *argv[])
{
// #是判断它的值是否为true
#if DEV_MODE01
printf("我是01!");
#endif
#if DEV_MODE02
printf("我是02!");
#endif
#if DEV_MODE03
printf("我是03!");
#endif
#if DEV_MODE04
printf("我是04!");
#endif
return 0;
}
头文件
C语言得头文件是扩展名为 .h 的文件,包含了函数声明和宏定义,被多个源文件中引用共享。
头文件分为两类:
1.编译器自带的头文件 ---> 用< >括起来
2.程序员编写的头文件 ---> 用" "括起来
例如:
c
#include <stdio.h> //编译器自带的头文件
#include "my_lib.h"//程序员编写的头文件
注意:引用头文件相当于复制头文件的内容,到对应的源文件中。
< >和" "的区别在于头文件的搜索路径不同:
< >编译器会到系统路径下查找头文件;
而使用" ",编译器首先在当前目录下查找头文件,如果没有找到,再到系统路径下查找,当然你也可以直接给绝对路径
不管是标准头文件,还是自定义头文件,都只能包含变量和函数的声明,不能包含定义,否则在多次引入时会引起重复定义错误。
并且为了防止重复定义的错误,我们会使用条件编译,如下:
c
#ifndef HEADER_FILE
#define HEADER_FILE
//头文件的内容
#endif
其实当我们自己写头文件的时候,可以每次直接先把这三行代码写上
这种结构就是通常所说的包装器 ifndef。当再次引用头文件时,条件为假,因为 HEADER_FILE 已定义。此时,预处理器会跳过文件的整个内容,编译器会忽略它。
常见的官方头文件:
