2023-08-28 C语言函数一定要在.h文件中声明吗

news2024/10/7 12:26:30

C语言函数一定要在.h文件中声明吗


老林的C语言新课, 想快速入门点此 <C 语言编程核心突破>


C语言函数一定要在.h文件中声明吗

  • 前言
  • 一、三种情况下的函数声明与定义策略
      • 单文件小练习
      • 多文件工程
        • 需要在多个文件调用的函数
        • 不需要跨文件调用的函数
  • 二、示例
      • 需要在多个文件调用的函数:
        • 不需要跨文件调用的函数:
  • 总结


前言

最近碰到个好问题, C语言函数一定要在.h文件中声明吗?

之所以说这是好问题, 因为它引发了一个工程问题, 如何组织函数代码文件.

这是一个非常必要理解的问题, 当涉及一个软件工程, 需要编写无数的文件, 如果不理解声明与定义分离, 很容易出bug.


一、三种情况下的函数声明与定义策略

单文件小练习

无需考虑, 用不用头文件单独声明都是可以的.

多文件工程

则需要组织文件, 情况比较复杂

需要在多个文件调用的函数

定义在C文件, 声明在.h文件

在没有定义函数的C文件中, 通过include头文件, 可以调用函数, 这个简单.

不需要跨文件调用的函数

定义在C文件, 声明.h文件, 或不声明.h文件都可以

但如果不在.h文件中声明, 那么.c文件中函数的相互调用, 一定要遵循先后顺序

通常也会先在最开始统一声明, 最后进行定义, 防止某个函数调用一个在其定义以后才声明的函数, 这个是不合法的.

对于非跨文件的函数, 请务必使用static关键字, 以防全局名称污染

二、示例

需要在多个文件调用的函数:

func.h

void func();

func.c

#include "func.h"

void func()
{语句...}

needFunc.c 需要引用func.h的C文件

#include "func.h"

void otherFunc()
{
	func(); // 调用func()
	语句...
}

这里的声明定义分离是十分必要的,

otherFunc()函数要调用func()函数, 有两种方式,

第一, 引入含func()函数声明的头文件

第二, 直接在needFunc.c文件中声明, 这种方式很笨, 而且文件多了容易出错.

不需要跨文件调用的函数:

func.h

void func1();
void func2();

func.c

#include "func.h"

int main()
{
	func2();
}

void func1()
{语句...}

void func2()
{
	func1();
	语句...
}

这里函数的声明和定义分开, 虽然func2()是需要调用func1()的, 但由于声明在func.h中, 所以实现的顺序是可以随意的,

也就是说, 无论是.h文件还是.c文件, 两个函数位置可以交换.

如果没有.h文件, 则可在.c文件中最开始进行函数的声明, 后面进行定义, 这个也是OK的,

如果仅仅在.c中直接定义, 那么函数的顺序则必须是func1()定义, 然后func2()定义, 否则func2()找不到func1()

对于大多数情况, 是一个.c文件中, 既有跨文件函数定义, 也有非跨文件函数定义,

比如, func1()仅仅是服务于func2(), func2()则被其它文件调用,

那么, 可以将func2()声明在.h中, func1()声明在.c中, 并加上static修饰,

func.h

void func2();

func.c

#include "func.h"

static void func1()
{语句...}

void func2()
{
	func1();
	语句...
}

这样func1()的作用域仅在此.c文件中, 不会干扰全局, 其它文件声明定义同样名为func1()的函数就不会出问题, 毕竟项目大了, 不好说函数不重名.


总结

一般教材, 对于文件的组织可能一笔带过, 对于初学者, 进行单文件小练习, 完全不重要, 所以被忽视, 一旦涉及到多文件, 自己实现库供其他人调用, 则文件组织就成了必修项目.


老林的C语言新课, 想快速入门点此 <C 语言编程核心突破>


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/941554.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一起参与开源,志愿者招募中!IT、翻译、新媒体、设计等

Hi 同学&#xff0c;你是不是专注某个领域&#xff0c;想找机会&#xff0c;积累开源软件方面的早期经验&#xff1f;你来对地方啦。请阅读本文&#xff0c;了解为什么要加入 ONLYOFFICE&#xff0c;做出贡献&#xff0c;以及如何做到。 贡献开源&#xff0c;福利多多 为开源项…

2023全国大学生数学建模竞赛B题思路模型代码

目录 一.思路模型见文末名片&#xff0c;比赛开始9.7晚上第一时间更新 二.国赛常用算法之随机森林 3.思路获取见此 一.思路模型见文末名片&#xff0c;比赛开始9.7晚上第一时间更新 二.国赛常用算法之随机森林 # -*- coding: utf-8 -*- """ author: Administ…

自动化运维工具-----Ansible入门详解

目录 一.Ansible简介 什么是Ansible&#xff1f; Ansible的特点 Ansible的架构 二.Ansible任务执行解析 ansible任务执行模式 ansible执行流程 ansible命令执行过程 三.Ansible配置解析 ansible的安装方式 ansible的程序结构&#xff08;yum安装为例&#xff09; ansibl…

11. 排兵布阵

目录 题目 思路&#xff08;贪心快排&#xff09; 注意事项 C代码 题目 排兵布阵 Description 总所周知&#xff0c;韩信是一位神勇的军事家。某日夜幕&#xff0c;敌方突然来袭&#xff0c;韩信作为塞外将帅吹响紧急的号角。各个帐内的士兵听见号角立即集合&#xff0c;站…

Python爬虫异常处理实践:处理被封禁和网站升级问题

在这篇文章中&#xff0c;我们将一起探讨Python爬虫异常处理实践&#xff0c;特别关注处理被封禁和网站升级问题。让我们一起来看看如何解决这些问题&#xff0c;提高我们爬虫程序的稳定性和可靠性。   首先&#xff0c;我们要了解为什么会遇到这些问题。网站封禁爬虫的原因主…

(六)k8s实战-存储管理

一、Volumes 1、HostPath 【使用场景&#xff1a;容器目录 挂载到 主机目录】 【可以持久化到主机上】 将节点上的文件或目录挂载到 Pod 上&#xff0c;此时该目录会变成持久化存储目录&#xff0c;即使 Pod 被删除后重启&#xff0c;也可以重新加载到该目录&#xff0c;该目…

最小化安装移动云大云操作系统--BCLinux-for-Euler-22.10-everything-x86_64-230316版

CentOS 结束技术支持&#xff0c;转为RHEL的前置stream版本后&#xff0c;国内开源Linux服务器OS生态转向了开源龙蜥和开源欧拉两大开源社区&#xff0c;对应衍生出了一系列商用Linux服务器系统。BCLinux-for-Euler-22.10是中国移动基于开源欧拉操作系统22.03社区版本深度定制的…

【halcon深度学习】图像分割数据集格式的转换

前言 目前用于**图像分割的**数据集&#xff0c;我目前接触到的用的比较多的有&#xff1a; 1 PASCAL VOC 2 COCO 3 YOLO 4 Halcon自己的格式&#xff08;其实就是Halcon字典类型&#xff09;当前我涉及到计算机视觉中的数据集格式有&#xff0c;PASCAL VOC、COCO 和 YOLO 用于…

天气插件和antv图表组件库的使用

目录 天气插件 antv组件库 特性 数据映射 data xField yField 图形样式 point state 图表组件 label tooltip 图表交互 添加交互 天气插件 网站:天气预报代码_天气预报插件_免费天气预报代码(插件)调用——天气网 (tianqi.com) 挑选想要的样式&#xff0c;点击 …

暴力递归转动态规划(一)

前两篇帖子介绍了暴力递归的过程&#xff0c;总的来说就是利用自然智慧不断的尝试。这篇文章则会介绍如何将暴力递归转成动态规划。 斐波那契数列 斐波那契数列一定都不陌生&#xff0c;规定第一列的值是1&#xff0c;第二列的值是2的话&#xff0c;那第七列的值就是13&#x…

2023Win11安装Oracle19c教程

2023Win11安装Oracle19c教程 一、下载安装二、安装三、配置四、navicat连接oracle 一、下载安装 进入官网&#xff0c;选择产品-Oracle DataBase&#xff0c;点击进入下载界面 点击跳转下载 选择19c进行下载 选择windows64位版本下载 登录账号后开始下载&#xff0c;等待下载…

1.3.1背包模型(一)

01背包 划分依据&#xff1a;依靠“最后一步”来划分 完全背包 多重背包 完全背包&#xff1a;求所有前缀的最大值 多重背包&#xff1a;求滑动窗口内的最大值 1.多重背包问题 III 有 N N N种物品和一个容量是 V V V的背包。 第 i i i种物品最多有 s i s_{i} si​件&…

激活函数总结(二十二):激活函数补充(Soft Exponential、ParametricLinear)

激活函数总结&#xff08;二十二&#xff09;&#xff1a;激活函数补充 1 引言2 激活函数2.1 Soft Exponential激活函数2.2 ParametricLinear激活函数 3. 总结 1 引言 在前面的文章中已经介绍了介绍了一系列激活函数 (Sigmoid、Tanh、ReLU、Leaky ReLU、PReLU、Swish、ELU、SE…

机器人制作开源方案 | 桌面级机械臂--仿真设计

1. Ros概述 ROS是一个适用于机器人编程的框架&#xff0c;这个框架把原本松散的零部件耦合在了一起&#xff0c;为它们提供了通信架构。ROS虽然叫做操作系统&#xff0c;但并非Windows、Mac那样通常意义的操作系统&#xff0c;它只是连接了操作系统和你开发的ROS应用程序&#…

AODV代码实现详解——原理与源码分析(一)

首先来几个标准参考&#xff1a; RFC 3561 RFC 3561 中文翻译 一个博客 挺好的另一个博客 事件&#xff1f; 字段长度&#xff1f; 事件驱动 各种定时器 状态转移图&#xff1f; AODV协议 基本概念 AODV&#xff08;Ad hoc On-Demand Distance Vector&#xff09;是一种基于…

Flutter问题记录 - Unable to find bundled Java version

新版本的Android Studio真的移除了JRE&#xff0c;jre目录找不到&#xff0c;怪不得报错了&#xff0c;不过多了一个jbr目录&#xff0c;找了个以前的Android Studio版本对比 搜了一下jbr&#xff08;JetBrains Runtime&#xff09;&#xff0c;原来IDEA老早就开始用了&#xf…

Redis 7 教程 数据持久化

总体 RDB 介绍 RDB 持久化以指定的时间间隔执行数据集的时间点快照 。 把某一时刻的数据和状态以文件的形式写到磁盘上,即使出现故障宕机,快照文件也不会丢失,数据的可靠性得到保证。快照文件就是RDB(Redis DataBase)文件(dump.rdb) 作用 在指定的时间间隔内将内存中的数…

财务数据分析怎么做?看看奥威BI数据可视化工具的解法

从以往的BI智能数据可视化分析项目来看&#xff0c;要想快刀砍乱麻地做好财务数据分析&#xff0c;为企业运营决策提供更加直观深入的数据支持&#xff0c;那就需要为财务数据分析做好数据导入、建模、报表制作、展示等多方面的准备。奥威BI数据可视化工具为此特意打造了一套标…

C#实战:基于腾讯OCR技术实现企业证书识别和数据提取实践

一、OCR技术介绍 在当今数字化时代&#xff0c;OCR&#xff08;Optical Character Recognition&#xff09;识别技术正发挥着越来越重要的作用。OCR技术通过将图像中的文字转化为可编辑的文本形式&#xff0c;实现了对大量纸质文档的数字化处理和信息提取。常见的有企业资质证…

【uniapp】 实现公共弹窗的封装以及调用

图例&#xff1a;红框区域为 “ 内容区域 ” 一、组件 <!-- 弹窗组件 --> <template> <view class"add_popup" v-if"person.isShowPopup"><view class"popup_cont" :style"{width:props.width&&props.width&…