当前位置: 首页 > ai >正文

头文件管理

目录

前言

头文件包含方式

头文件包含方案一

目录结构

文件内容

Makefile编写

头文件包含方案二

目录结构

最佳实践

规范写法总结

Linux头文件包含方案思考


前言

由于工程项目中所涉及的头文件与源文件数量庞大,可以看见各种各样的头文件的包含方式, 当引入了Makefile自动化编译工程时,笔者实际操作时发现头文件的包含远远不止表面现象那么简单,背后的原因需要深究才能帮助笔者建立理性的分析思路,所以需要探讨常见场景下的头文件包含方案;

头文件包含方式

当编译器在处理 #include "file.h" 时,会将源文件的绝对路径作为基准,源文件所在目录(即.c/.cc文件所在目录),由于目录结构本质为一种命名空间,源文件目录作为 "本地命名空间",优先于全局系统目录,所以最先查找源文件所在目录

-I 选项在预处理阶段直接扩展头文件搜索路径,为了满足开发者对自定义头文件的优先引用需求,若编译器先搜索系统目录,会导致用户自定义头文件被系统同名文件覆盖开发者通过-I显式指定本地头文件路径,确保自定义内容优先被引用;

系统默认头文件目录是编译器在编译过程中自动搜索标准库头文件的位置,我们采用如下指令来查看 GCC 编译器的详细编译过程及默认头文件搜索路径

# 将空设备文件/dev/null作为标准输入传递给编译器并输出预处理阶段详细的信息gcc -v -E - < /dev/null

采用-I 选项设置头文件搜索路径为inc,通过cpp -v 命令查看预处理阶段的搜索路径是否被成功设置;

cpp -v -I ./inc - < /dev/null

头文件包含方案一

目录结构

文件内容

Makefile编写

# 工具链配置
CC=gcc
# 头文件位置
INC_DIRS=./inc
# 编译器选项配置
CFLAGS=-Wall -O2 -std=c99 -I$(INC_DIRS)
# 目标名称
TARGET=main
# 源文件位置
SRC_DIRS=./src# 源文件列表
SRCS= $(SRC_DIRS)/file1.c $(SRC_DIRS)/file2.c $(SRC_DIRS)/file3.c $(SRC_DIRS)/main.c# 编译
$(TARGET):$(SRCS:.c=.o)$(CC) $^ -o $@
%.o:%.c$(CC) $(CFLAGS) $< -c -o $@.PHONY:clean
clean:rm -rf $(TARGET) $(SRCS:.c=.o)

Makefile中 编译器选项配置 通过 -I选项 告知编译器去 ./inc目录 搜索头文件,通过编译运行进而判断此种头文件包含方式是否成功;

头文件包含方案二

目录结构

将方案一目录结构修改为方案二,不改变Makefile中 -I选项,makefile不发生任何变化,首先file.h文件位置的变化影响到main.c文件与file1.c文件,此时main.c文件与file1.c文件应该如何包含file1.h(file2.c file3.c file1.h file2.h file3.h内容同方案一)

通过编译运行检测此种包含头文件的方案是否可以保证编译器找到头文件的位置;

结论:只有当 头文件位于 -I 指定目录的子目录中 时,才需要在 #include 中写子目录路径;

最佳实践

-I 管理路径,#include 只关心 "文件名 + 层级"

  • -I 选项:用于告知编译器 "头文件的根搜索目录是什么"(如 inc/ 目录);
  • #include 语句:用于告知编译器 "头文件在根搜索目录下的相对路径是什么"(如 file1.h 或 utils/file1.h);

规范写法总结

Linux头文件包含方案思考

当采用Linux进行系统编程或者网络编程时,通常书写头文件的方式如下,原因又是什么呢

#include <sys/types.h>    // 基本系统数据类型
#include <sys/stat.h>     // 文件状态
#include <sys/socket.h>   // 套接字接口

Unix/Linux 系统设计遵循 "目录即命名空间" 原则,通过文件系统路径实现功能隔离,编译器会自动递归搜索系统默认头文件路径下的所有子目录,Linux系统可以轻松获得头文件的路径,但是为啥我们需要采用 #include<目录名/文件名> 头文件格式呢?

假如直接采用 #include <types.h> , 编译器无法确定是:/usr/include/sys/types.h(POSIX 标准)/usr/include/linux/types.h(Linux 内核)

Linux底层系统调用接口采用 #include<目录名/文件名>格式 使得用户可以显式指定头文件的功能模块和来源,避免命名冲突

实践方案

Linux系统头文件:    直接用 <目录名/文件名>, 无需 -I 指定头文件搜索路径;第三方库(BOOST):    用 -I指定库的根目录, 头文件用 <库名/文件名>

http://www.xdnf.cn/news/13814.html

相关文章:

  • 1.线性表的顺序存储-顺序表
  • FastAPI基础入门(四)
  • 【推荐算法课程二】推荐算法介绍-深度学习算法
  • cocos android打包 错误总结
  • QCoreApplication QApplication
  • 【2025】Ubuntu22.04深度学习环境搭建记录
  • Java常用类库大全(学习笔记)持续更新中
  • JS手写代码篇---手写sleep
  • fbx导入blender结构错乱,但在threejs中加载正常
  • 【Python打卡Day36】信贷项目的神经网络训练@浙大疏锦行
  • HALCON第三讲->特征提取
  • HTML常用标签(上)
  • 位运算基础
  • 强化微调技术与GRPO算法(2): 优势、应用场景与选择指南
  • python程序设计(2)
  • AI Agent的记忆体系与架构设计
  • QEMU源码全解析 —— 块设备虚拟化(27)
  • vue下的xlsx文件导出和导入的写法
  • 重要的城市(图论 最短路)
  • ESP32-CAM识别解析QR二维码输出数据
  • D3.js研发分区柱状图
  • 电子垃圾之涂鸦控制板
  • 题解:CF2093B Expensive Number
  • C++面试(8)-----求链表中环的入口节点
  • C++面试(6)-----调整数组顺序使奇数位于偶数前面
  • CodeForces 1453C. Triangles
  • QOpenGLWidget 中能同时显示 .step 的结构树和渲染图吗
  • 快递鸟电商退换货技术全解析:构建智能化逆向物流管理体系
  • IT运维的365天--028 批处理自行检测并以管理员权限运行
  • vue3 常见引用