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

常见的官方头文件:

相关推荐
葵花楹6 分钟前
【算法题】【动态规划2】【背包动态规划】
算法·动态规划
数研小生8 分钟前
1688商品列表API:高效触达批发电商海量商品数据的技术方案
大数据·python·算法·信息可视化·json
Coder_Boy_10 分钟前
基于SpringAI的在线考试系统-企业级教育考试系统核心架构(完善版)
开发语言·人工智能·spring boot·python·架构·领域驱动
前端玖耀里10 分钟前
Linux C/C++ 中系统调用与库函数调用的区别
linux·c语言·c++
2301_7657031415 分钟前
C++中的代理模式变体
开发语言·c++·算法
咚为16 分钟前
Rust tokio:Task ≠ Thread:Tokio 调度模型中的“假并发”与真实代价
开发语言·后端·rust
灰子学技术21 分钟前
性能分析工具比较pprof、perf、valgrind、asan
java·开发语言
酉鬼女又兒25 分钟前
27. 移除元素
数据结构·算法·排序算法
Minilinux201825 分钟前
Google ProtoBuf 简介
开发语言·google·protobuf·protobuf介绍
大尚来也28 分钟前
看不见的加速器:深入理解 Linux 页缓存如何提升 I/O 性能
java·开发语言