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

C语言18--头文件

头文件的作用

通常,一个常规的C语言程序会包含多个源码文件(.c),当某些公共资源需要在各个源码文件中使用时,为了避免多次编写相同的代码,一般的做法是将这些大家都需要用到的公共资源放入头文件(.h)当中,然后在各个源码文件中直接包含即可。

头文件的内容

  • 头文件中所存放的内容,就是各个源码文件的彼此可见的公共资源,包括:
  1. 全局变量的声明。
  2. 普通函数的声明。
  3. 静态函数的定义。
  4. 宏定义。
  5. 结构体、联合体的声明。
  6. 枚举常量列表的声明。
  7. 其他头文件。

示例代码:

// head.h
extern int global; // 1,全局变量的声明
extern void f1();  // 2,普通函数的声明
static void f2()   // 3,静态函数的定义
{...
}
#define MAX(a, b) ((a)>(b)?(a):(b)) // 4,宏定义
struct node    // 5,结构体的定义
{...
};
union attr    // 6,联合体的定义
{...
};
#include <unistd.h> // 7,其他头文件
#include <string.h>
#include <stdint.h>
  • 特别说明:
    1. 全局变量、普通函数的定义一般出现在某个源文件(*.c *.cpp)中,其他的源文件想要使用都需要进行声明,因此声明语句一般放在头文件中更方便。
    2. 静态函数、宏定义、结构体、联合体的声明都只能在其所在的文件可见,因此如果多个源文件都需要使用的话,放到头文件中定义是最方便,也是最安全的选择。

头文件的使用

头文件编写好了之后,就可以被各个所需要的源码文件包含了,包含头文件的语句就是如下预处理指令:

// main.c
#include "head.h"  // 包含自定义的头文件
#include <stdio.h> // 包含系统预定义的文件int main()
{...
}

头文件包含的细节:

#include <stdio.h>  
/*
#include <...> search starts here:   <>默认从以下系统路径寻找/usr/lib/gcc/x86_64-linux-gnu/11/include/usr/local/include/usr/include/x86_64-linux-gnu/usr/include
End of search list.*/#include "./inc/myHead.h"  // 使用双引号包含的头文件会从当前代码所处的路径下搜索
// 由于一般我们自己写的头文件会于项目存放在同一个路径下
// 因此一般会使用双引号来包含自己(非系统的头文件)编写的头文件
// 以上例子中有写该头文件的详细路径,因此编译时直接gcc 即可#include "myHead.h" // 没有写明头文件的具体相对路径
// 因此编译时需要告知编译器被你存储与哪个文件
gcc  xxx.c   -I./inc 
-I 用于告知编译器头文件的路径
./inc  则是具体的路径值

可以看到,在源码文件中包含指定的头文件有两种不同的形式:

  • 使用双引号:在指定位置 + 系统标准路径搜索 head.h
  • 使用尖括号:在系统标准路径搜索 stdio.h

由于自定义的头文件一般放在源码文件的周围,因此需要在编译的时候通过特定的选项来指定位置,而系统头文件都统一放在标准路径下,一般无需指定位置。

假设在源码文件 main.c 中,包含了两个头文件:head.h 和 stdio.h ,由于他们一个是自定义头文件,一个是系统标准头文件,前者放在项目 pro/inc 路径下,后者存放于系统头文件标准路径下(一般位于 /usr/include),因此对于这个程序的编译指令应写作:

gec@ubuntu:~/pro$ gcc main.c -o main -I./inc

头文件的格式

由于头文件包含指令 #include 的本质是复制粘贴,并且一个头文件中可以嵌套包含其他头文件,因此很容易出现一种情况是:头文件被重复包含。

  • 使用条件编译,解决头文件重复包含的问题,格式如下:
    • 作用:防止头文件被多次重复包含后出现重复定义的问题
#ifndef _HEADNAME_H   
#define _HEADNAME_H...
... (头文件正文)
...#endif

其中,HEADNAME一般取头文件名称的大写

项目的基本框架:

编译命令:

gcc src/*.c -o bin/demo -I./incgcc         #编译命令
src/*.c     #需要编译的源文件 *.c 表示该路径下的所有.c文件
-o          #指明输出的文件名字
bin/demo    #具体输出的可执行文件路径+名字
-I./inc     # -I指定头文件的路径 ./inc 具体的路径

C语言的关键字:

在C语言中,以下是一些关键字及其作用:1. #include:预处理指令,用于包含头文件。例如:#include <stdio.h> 包含头文件 stdio.h,以便使用其中的函数。2. #define:预处理指令,用于定义宏。例如:#define MAX 1000 定义一个宏 MAX,值为 1000。3. #undef:预处理指令,用于取消定义宏。例如:#undef MAX 取消定义宏 MAX。4. #ifdef:预处理指令,用于检查当前定义的宏是否已定义。例如:#ifdef MACRO 检查是否定义了宏 MACRO。5. #ifndef:预处理指令,用于检查当前定义的宏是否未定义。例如:#ifndef MACRO 检查是否未定义宏 MACRO。6. #else:预处理指令,用于实现条件编译。例如:#ifdef MACRO #else 表示当宏 MACRO 已定义时执行 #else 中的代码。7. #elif:预处理指令,用于实现条件编译的 elif 分支。例如:#ifdef MACRO #elif MACRO2 表示当宏 MACRO 已定义时执行 #elif MACRO2 中的代码。8. #endif:预处理指令,用于结束条件编译。例如:#endif 结束条件编译。9. #error:预处理指令,用于生成错误信息。例如:#error "Error message" 生成错误信息 "Error message"。10. #pragma:预处理指令,用于提供编译器特定的信息。例如:#pragma pack(1) 告诉编译器使用大小为 1 的对齐方式。11. #volatile:预处理指令,用于指示对变量的访问应该使用寄存器方式。例如:#volatile 修饰的变量在汇编语言中不会被优化。12. #restrict:预处理指令,用于提示编译器使用 restrict 属性。例如:#restrict int *a 修饰的指针 a,编译器会使用 restrict 属性。13. auto:关键字,用于指定变量为自动变量。例如:auto int a 声明一个自动变量 a。14. static:关键字,用于指定变量为静态变量。例如:static int a 声明一个静态变量 a。15. register:关键字,用于指定变量为寄存器变量。例如:register int a 声明一个寄存器变量 a。16. volatile:关键字,用于指定变量为 volatile 变量。例如:volatile int a 声明一个 volatile 变量 a。17. const:关键字,用于指定变量为常量。例如:const int a 声明一个常量变量 a。18. inline:关键字,用于指定函数为内联函数。例如:inline void func() { ... } 声明一个内联函数 func。19. extern:关键字,用于指定变量为外部变量。例如:extern int a 声明一个外部变量 a。20. __cdecl、__stdcall、__fastcall、__thiscall:调用约定,用于指定函数的调用方式。例如:__cdecl void func() { ... } 声明一个使用 __cdecl 调用约定函数 func。21. __attribute__:属性,用于指定函数的属性,如限制参数数量、设置栈大小等。例如:__attribute__((stdcall)) void func(int arg) { ... } 声明一个使用 stdcall 调用约定函数 func,并限制参数数量为 int arg。22. __packed:属性,用于指定变量或结构体的对齐方式。例如:__packed int a 声明一个使用 __packed 属性变量 a。23. __section:属性,用于指定变量或结构体放置的节区。例如:__section(".data") int a 声明一个使用 __section(".data") 属性变量 a。24. __alignof__:运算符,用于获取变量或类型的对齐字节数。例如:__alignof__(int) 获取 int 类型的对齐字节数。25. __builtin_offsetof:函数,用于获取结构体中成员的偏移量。例如:__builtin_offsetof(struct my_struct, my_member) 获取 struct my_struct 中的 my_member 成员的偏移量。26. __has_feature:宏,用于检查编译器是否具有某些特性。例如:__has_feature(c++11) 检查编译器是否具有 c++11 特性。27. __is_available:宏,用于检查某个特性是否可用。例如:__is_available("avx") 检查 avx 特性是否可用。28. __clang_builtin_macro:宏,用于检查某个宏是否为 clang 内置宏。例如:__clang_builtin_macro("__clang_max__") 检查 __clang_max__ 是否为 clang 内置宏。29. __GNUC_MINOR__:宏,用于获取 gcc 版本的小版本号。例如:__GNUC_MINOR__ 获取 gcc 的 minor 版本号。30. __GNUC_PATCHLEVEL__:宏,用于获取 gcc 版本的补丁版本号。例如:__GNUC_PATCHLEVEL__ 获取 gcc 的 patchlevel 版本号。

结语:

        在这篇博客中,我们详细探讨了C语言中头文件的概念及其重要性。头文件作为代码组织的一部分,不仅便利了函数和变量的声明,也使得不同源文件之间的协作变得更加高效。通过合理地使用头文件,我们能够模块化代码,提高可读性和可维护性。

        此外,了解如何创建和管理自定义头文件,能够帮助我们减少代码重复,提升项目的结构性。在实际开发中,正确使用头文件可以降低错误的发生率,并使调试过程更加顺畅。

        希望这篇文章能够帮助您深入理解C语言中的头文件,以及如何在项目中有效地使用它们。随着编程技能的提升,对代码结构和组织方式的重视将为您的开发工作带来长远的好处。感谢您的阅读,期待与您在今后的讨论中共同分享和学习更多编程知识!

相关文章:

C语言18--头文件

头文件的作用 通常&#xff0c;一个常规的C语言程序会包含多个源码文件&#xff08;.c&#xff09;&#xff0c;当某些公共资源需要在各个源码文件中使用时&#xff0c;为了避免多次编写相同的代码&#xff0c;一般的做法是将这些大家都需要用到的公共资源放入头文件&#xff…...

vscode软件在 C发中常用插件

一. 简介 本文简单介绍一下&#xff0c;当做 C开发时 vscode软件常用的插件。 vscode软件是 微软公司目前提供的一款免费的开发软件&#xff0c;可以通过 vscode官网下载 vscode。 二. vscode软件在 C开发中常用插件 注意&#xff1a;vscode软件安装后&#xff0c;可以直接…...

【C++ Primer Plus习题】17.2

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: #include <iostream> #include <fstream> using namesp…...

Vue Props传值

Props用于父组件向子组件传值 定义类型 // 定义一个接口,用来限制Teacher的属性 export interface Teacher {name: string;age: number;gender: string; }export type teacherList Teacher[];// 一个自定义类型 export type Teachers Array<Teacher>;父组件 <scr…...

FreeSWITCH event_socket 配置从其他地址连接

FreeSWITCH 默认配置只能 在本机连接, 要从 其他ip连接, 需要如下配置&#xff1a; 1、修改event_socket.conf.xml 1 <configuration name"event_socket.conf" description"Socket Client">2 <settings>3 <param name"nat-map&…...

信息安全数学基础(19)同余式的基本概念及一次同余式

一、同余式概念 同余式是数论中的一个基本概念&#xff0c;用于描述两个数在除以某个数时所得的余数相同的情况。具体地&#xff0c;设m是一个正整数&#xff0c;a和b是两个整数&#xff0c;如果a和b除以m的余数相同&#xff0c;则称a和b模m同余&#xff0c;记作a≡b(mod m)。反…...

网关过滤器:Spring Cloud Gateway

在Java中&#xff0c;实现网关过滤器&#xff08;Gateway Filter&#xff09;通常与Spring Cloud Gateway相关。Spring Cloud Gateway是一个基于Spring Framework 5、Project Reactor和Spring WebFlux构建的API网关&#xff0c;它为微服务架构提供了一种简单而有效的方式来路由…...

力扣最热一百题——除自身以外数组的乘积

目录 题目链接&#xff1a;238. 除自身以外数组的乘积 - 力扣&#xff08;LeetCode&#xff09; 题目描述 示例 提示&#xff1a; 解法一&#xff1a;左右数组&#xff08;小型动态规划&#xff09; 实现思路 Java写法&#xff1a; 运行时间 C写法&#xff1a; 运行时…...

监控易监测对象及指标之:全面监控SQL Server数据库

随着企业信息化建设的深入&#xff0c;数据库作为核心数据资产的管理中心&#xff0c;其性能和稳定性直接关系到业务的连续性和企业的运营效率。SQL Server作为一款功能强大、性能稳定的关系型数据库管理系统&#xff0c;广泛应用于各类业务场景中。 为了确保SQL Server数据库的…...

计算机视觉的应用34-基于CV领域的人脸关键点特征智能提取的技术方法

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下计算机视觉的应用34-基于CV领域的人脸关键点特征智能提取的技术方法。本文主要探讨计算机视觉领域中人脸关键点特征智能提取的技术方法。详细介绍了基于卷积神经网络模型进行人脸关键点提取的过程&#xff0c;包括使…...

What is new in .NET 8 and C#12

目录 What is new in .NET 8? .NET Aspire Core .NET Libraries Metrics软件度量 Networking Extension Libraries Garbage Collection Reflection Improvements Native AOT Support NET SDK What is new in C# 12 ? Primary Constructors Collection Expressio…...

基于R语言的统计分析基础:使用键盘输入数据

在R语言中&#xff0c;键盘输入数据是一种灵活且直接的数据获取方式&#xff0c;适用于处理小数据集或需要即时用户交互的场景。通常用于交互式数据探索和分析、临时数据处理、交互式图形绘制、脚本自动化中的用户交互、特定应用场景下的数据录入中。 比如利用readline()函数根…...

unity3d入门教程九

unity3d入门教程九 20.2播放音频20.3在代码中播放21.1延时调用21.2invoke API21.3消息调用22.1交互界面22.2添加canvas22.3canavas的位置22.4添加text 这里给一个资源网站&#xff0c;可以部分免费下载&#xff0c;音乐和音效超多&#xff0c;支持检索 爱给网 https://www.aige…...

着色器 简介

着色器&#xff08;Shader&#xff09;是运行在 GPU 上的小程序。这些小程序为图形渲染管线的某个特定部分而运行。从基本意义上来说&#xff0c;着色器只是一种把输入转化为输出的程序。着色器也是一种非常独立的程序&#xff0c;因为它们之间不能相互通信&#xff1b;它们之间…...

redis单点、主从、哨兵、集群的不同

redis哨兵模式有几个&#xff1a; 单点主从哨兵集群 区别 主从模式&#xff1a;读写分离。 哨兵模式&#xff1a;哨兵模式是在主从模式的基础上添加了故障检测和自动故障转移的功能。还是读写分离。 哨兵节点负责监控主节点和从节点的状态&#xff0c;并在主节点宕机时选举新…...

notepad++的json查看

json文件查看 因为接触到3dtile模型&#xff0c;所以经常需要和json打交道&#xff0c;但是很多模型是下面这种情况&#xff0c;不好阅读&#xff0c;所以可以使用notepad的插件查看 正常打开是这样的 加载notepad插件 搜索json下载安装就可以了 如果网络抽象&#xff0c;下载…...

基于无人机影像的可见光单木分割数据集-json格式

基于无人机影像的可见光单木分割数据集&#xff0c;共1700张影像&#xff0c;数据集大小3.6GB&#xff0c;分割标注采用标准json格式。 该数据集是一个专门用于基于无人机可见光影像进行单木分割的数据集&#xff0c;旨在帮助研究人员和开发者训练和评估基于深度学习的图像分割…...

毕业设计选题:基于ssm+vue+uniapp的捷邻小程序

开发语言&#xff1a;Java框架&#xff1a;ssmuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;M…...

【毕业设计】基于 PHP 开发的社区交流系统

基于 PHP 开发的社区交流系统可以是一个论坛、博客平台或是问答网站等形式的在线平台&#xff0c;用于用户之间的互动交流。以下是一个简单的 PHP 社区交流系统的示例&#xff0c;包括用户注册、登录、发布帖子、回复帖子等功能。 技术栈 前端&#xff1a;HTML, CSS, JavaScr…...

RK3568 解决Ubuntu加载驱动模块报错以及开机启动如何自动加载模块

遇到问题是,当我在buildroot文件系统跑这个ko文件,是可以正常使用的,但是在Ubuntu上却跑不了,提示:insmod: ERROR: could not insert module analyze_inode.ko: Operation not permitted 参考其他博主的博客,其实只要添加sudo即可,可能是权限问题导致无法加载,这里记录…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...

高效的后台管理系统——可进行二次开发

随着互联网技术的迅猛发展&#xff0c;企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心&#xff0c;成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统&#xff0c;它不仅支持跨平台应用&#xff0c;还能提供丰富…...

Java中栈的多种实现类详解

Java中栈的多种实现类详解&#xff1a;Stack、LinkedList与ArrayDeque全方位对比 前言一、Stack类——Java最早的栈实现1.1 Stack类简介1.2 常用方法1.3 优缺点分析 二、LinkedList类——灵活的双端链表2.1 LinkedList类简介2.2 常用方法2.3 优缺点分析 三、ArrayDeque类——高…...

【Zephyr 系列 16】构建 BLE + LoRa 协同通信系统:网关转发与混合调度实战

🧠关键词:Zephyr、BLE、LoRa、混合通信、事件驱动、网关中继、低功耗调度 📌面向读者:希望将 BLE 和 LoRa 结合应用于资产追踪、环境监测、远程数据采集等场景的开发者 📊篇幅预计:5300+ 字 🧭 背景与需求 在许多 IoT 项目中,单一通信方式往往难以兼顾近场数据采集…...

Electron简介(附电子书学习资料)

一、什么是Electron&#xff1f; Electron 是一个由 GitHub 开发的 开源框架&#xff0c;允许开发者使用 Web技术&#xff08;HTML、CSS、JavaScript&#xff09; 构建跨平台的桌面应用程序&#xff08;Windows、macOS、Linux&#xff09;。它将 Chromium浏览器内核 和 Node.j…...