C语言之头文件,宏和条件编译

文章目录


宏

宏(macro)其实就是一个特定的字符串,用来直接替换。 在预处理阶段就会被替换。

  1. 使得程序的可读取有所提高,使用一个又有意义的单词来表示一个无意义数字(某个值)
  2. 方便对代码进行迭代更新, 如果代码中有多处使用到该值, 则只需要修改一处即可(定义)
  3. 提高程序的执行效率,可以使用宏来实现一个比较简单的操作。用来替代函数的调用-有点儿类似内联函数。

使用:

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));
}

宏只是直接文本替换,没有任何的判断以及语法检查的操作甚至运算

宏在编译的第一个阶段(预处理), 被处理完成,运行的过程中不占用时间(宏已经不存在)宏在预处理的时候直接展开。

  1. 有参宏: 只是文本替换,复杂的运算在里面可能出现问题。

  2. 宏只能写在同一行中(逻辑行),如果迫不得已需要使用多行来写一个宏则可以使用转义字符\把换行符转义掉


条件编译

在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 已定义。此时,预处理器会跳过文件的整个内容,编译器会忽略它。

常见的官方头文件:

相关推荐
李纲明3 小时前
WordPress 白屏排查手册:关插件、换主题、开调试、查 PHP(附停手信号)
开发语言·php·wordpress·故障排查·白屏·插件冲突
ShineWinsu3 小时前
对于JavaScript:JavaScript基础语法的解析
开发语言·前端·javascript·面试·web·基础语法·循环
erzong2313 小时前
Linux操作系统:线程概念与控制
linux·算法
普通人64 小时前
php+html+canvas实现树状打开的结构
开发语言·javascript·html5·1024程序员节
wuminyu4 小时前
JMM学习总结:深入理解happens-before关系
java·linux·c语言·jvm·c++
电商API_180079052474 小时前
反向海淘多币种结算:汇率该在哪个时点被冻结
java·开发语言·数据库·跨境电商·1688 api
Nil2084 小时前
leetcode 5最长回文子串
算法·leetcode·职场和发展
xxwl5854 小时前
区域赛分类题解
c++·笔记·学习·算法
m0_674571974 小时前
力扣 hot 100 python
python·算法·leetcode
开开心心就好5 小时前
多份文档怎么批量打印?支持多种格式
java·服务器·开发语言·pdf·ocr·散列表·启发式算法