(C语言)头文件实现的函数

(C语言)头文件实现的函数

http://www.diybl.com/ 2008-11-16  网络 点击: 239   [ 评论 ]
文章搜索:      【点击打包该文章】   
【本站开通在线QQ讨论群】

在C语言里面,有时候为了方便(方便的同义词是偷懒),函数就直接在头文件里面实现了。那么这样子有什么问题呢?

下面举个例子,这个例子只有3个文件

/* fun.h */
#ifndef FUN_H
#define FUN_H
void base(){};
void fun();
#endif 

/* fun.c */
#include "fun.h"
void fun()
{
    base();
}

/* main.c */
#include "fun.h"
int main()
{
    fun();
    return 0;
}

好,然后gcc一下

gcc -c main.c (通过)
gcc -c fun.c  (通过)
gcc -o main main.o fun.o (链接错误)

出现错误...“base()函数重定义!”

为什么重定义呢?因为#include是预处理部分,在编译之前由预处理程序在这个部分复制头文件的内容过来。所以在编译时候,main.o和fun.o文件都有base()函数的定义。那么链接程序就不知道链接那个定义好了(二义性啊)

如何解决呢,为了实现“声明和实现分开”这个目标最好就是把这个base函数的函数体移到源文件里面。如果由于某种原因真的要放在头文件中...也可以。

用static声明就可以了,静态函数的作用域是文件,而不是全局。比如,上面的例子将头文件里面的void base(){}改成static void base(){},那就OK。

这个static在c语言中的用法可以google下,上面的资料好多很详细滴。

顺便说说头文件的循环依赖的问题。

比如有三个头文件a.h b.h c.h,a.h里面有#include "b.h",b.h里面有#include "c.h", c.h里面有#include "a.h",那就会造成文件的循环依赖,后果是什么呢?

比如有个文件a.c,上面有#include "a.h",那在a.c文件编译之前,预处理程序就会不断的把这三个头文件的内容复制过来,超过了一定的数量,就会导致“头文件数太多”的编译错误。

解决方法呢,当然就是常见的#ifndef...#define...#endif组合了。不过要把前两个写在头文件的开头(一定是开头),最后一个写在最末尾。

这样的话,第一次展开a.h b.h c.h的时候就已经定义了宏,到了c.h中的#include "a.h"时候,遇到了#ifndef,由于这个宏在上一次展开时已经定义了,所以这部分就跳过去了。也就是每个头文件最多只在每个源文件里面包含一次。

但是即使编译链接没有问题,循环依赖也会降低开发效率,为什么?因为文件都在依赖,比如某一天,要改变a.h的一部分内容,然后所有依赖于a.h b.h c.h的文件都得重新编译...链接;所以现在的C++有“前向声明”的技巧可以缓解这个问题。(缓解并不是解决。)而JAVA运用的import机制就很好的解决了这个问题,真正实现了“实现与声明相分离”这个目标。

LeetCode 面试经典 150 题回顾 最经典 150 题,掌握面试所有知识点 面试经典 150 题 : 题目分析、解题思路、复杂度分析、代码展示 阅读详情

相关推荐

CTF实战:Wireshark数据包分析从入门到精通(附经典题型解析)

本文详细介绍了Wireshark在CTF比赛中的数据包分析技巧,从基础抓包到高级协议解析,涵盖HTTP流量分析、USB键盘数据还原等实战案例。通过经典题型解析,帮助读者掌握精准过滤、文件提取等核心技能,提升CTF竞赛中的网络流量分析能力。

pz890123的博客 587

educoder线索二叉树第1关:头文件基本函数的实现

任务描述 本关任务:实现本实训所需头文件的基本函数。 相关知识 实验目的 掌握线索二叉树的有关知识; 掌握求解线索二叉树中结点前趋和后继的算法以及以相应次序遍历线索二叉树的算法; 掌握二叉树的线索化算法的设计。 线索二叉树是为了快速求解二叉树中结点在指定次序下的前驱和后继,而将二叉链表中空的左右孩子指针分别改为指向其前驱和后继结点而得到的结构,反映了运算对数据结构的设计的影响。因此,首先要了解线索二叉树的结构特点,其中原本为空的指针被修改为前驱和后继指针,使得对左右子树和线索的判断发生了变化。利用线索可以实

qq_46118539的博客 8326

spoon工具的常用基础操作

先创建一个作业,这个作业流程,包括进行设置变量转换,查询结果输出转换,方便后续循环。整个流程写完后,执行作业5_执行整个流程,成功后,可以在数据库查看结果。,新建一个转换,excel表输入然后复制记录到结果,保存转换文件。这三个用户下 都有一张emp表 分别是 三个部门的用户信息。,新建一个数据库连接,变量命名用户名和密码。成功执行后,可以到保存的excel位置进行查看。emp表输入,可以进行预览查看数据有没有过来。输出到一直excel表,运行结果输出。,新建一个转换,拖拽。

qq_43583887的博客 5831

二叉树实验

数据结构C语言版

aiains的博客 3500

手把手教你用MATLAB/Simulink模拟微电网潮流方向(附代码下载)

本文提供了一份详细的MATLAB/Simulink微电网潮流仿真实战指南。通过手把手教学,指导读者从零搭建包含光伏、储能和负荷的微电网模型,并模拟并网、孤岛等多种运行场景下的潮流方向变化。文章核心在于利用Simulink实现微电网的动态潮流分析与可视化,帮助工程师深入理解分布式能源系统中的功率平衡与控制策略。

weixin_28314575的博客 107

看完就会!手把手教您如何正确开启飞牛Nas 虚拟机的 IOMMU 硬件直通,让虚拟机的性能飙升!

看完就会!手把手教您如何正确开启飞牛Nas 虚拟机的 IOMMU 硬件直通,让虚拟机的性能飙升!

XiaoqiangClub的博客 1万+

为什么不推荐在头文件中直接定义函数?

这篇技术博客探讨了为什么不推荐在头文件中直接定义函数。它解释了在将函数定义放在头文件中的潜在问题,并提供了更好的替代方案。通过避免在头文件中定义函数,读者可以更好地管理代码的复杂性,并提高代码的可读性和可维护性

生活不易,喵喵叹气 3154

osg点云加载与渲染

osg点云加载与渲染

cangqiongxiaoye的博客 821

线索二叉树实验

【代码】线索二叉树实验。

m0_61820263的博客 1256

uni-app - 解决 H5 微信公众号授权登录后,无法回退到 “上一页“ 的问题(微信登录后如何返回到触发它的那一页?无法通过 uni.navigateBack() 返回到前一页的问题?)详细教程

uniappH5微信登录重定向后无法返回到原来进入前的页面了,uni-appH5微信浏览器中授权微信登录后,无法正常回退问题,uniappH5微信登录后怎么返回上一页,uniapp公众号登陆后使用uni.navigateBack()回不去上一页,uniapp微信登录成功后返回页面后一直自动刷新页面,uniapph5授权成功后如何返回上一页,uniappH5微信登录后怎么返回到触发它的那一页去,公众号h5在授权后如何跳转回到刚进入时的页面,微信公众号H5网页返回上一页疑问,解决微信H5静默授

🏆 前端领域优质创作者 7715

软考高级网络规划设计师教程(第3版)

"本书是由工业和信息化部教育与考试中心组织编写的考试用书,依据《网络规划设计师考试大纲》(2026年审定通过)编写。本书分为两篇:第一篇为网络规划与设计综合知识,其中第1章介绍计算机网络基础知识,第2章介绍网络互连与互联网,第3章介绍网络规划与设计的知识和方法,第4章介绍网络资源设备,第5章介绍网络安全技术,第6章介绍标准化和网络安全法规;第二篇为案例实践,其中第7章介绍网络规划案例,第8章介绍网络故障分析与处理案例,第9章介绍网络安全部署案例,第10章介绍网络规划与设计论文写作的指导思想和写作技巧。

鹿鸣天涯 3943

C++语言基础_第一讲:头文件、输入输出、格式、基本运算

程序 = 数据结构 + 算法 C++ 是在C语言基础上开发的一种集面向对象编程、泛型编程和过程化编程于一体的编程语言。不同于C语言,C++是一种面向对象的语言,在C语言的基础上,C++扩充了一些自己特有的知识,如bool类型、重载函数、模版、STL等。

weixin_42730572的博客 1579

手把手教你学PCIE(2.1.23)--PCIe基本概念:链路速率协商

链路速率协商是一个多步骤的过程,确保发送端和接收端之间的链路速率设置一致。通过初始化链路速率寄存器、发送和接收 TS2 序列、检测链路对端的存在、交换链路速率信息、确定最大链路速率和配置链路速率,可以确保 PCIe 设备之间的数据传输速度最大化,从而提高数据传输效率。初始化链路速率寄存器:设置支持的最大链路速率。发送和接收 TS2 序列:检测链路对端的存在。交换链路速率信息:发送和支持的最大链路速率。确定最大链路速率:选择最小值作为最终链路速率。配置链路速率:更新链路速率寄存器。

MHD0815的博客 1816

C语言当中头文件<string.h>当中一些库函数的拟实现

C语言当中头文件<string.h>当中一些库函数的拟实现

2301_80205070的博客 1160

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

c语言isupper函数头文件,C语言isupper函数介绍、示例和实现

C语言isupper函数用于判断字符是否为大写字母(A-Z)。在本文中,我们先来介绍isupper函数的使用方法,然后编写一个自定义的_isupper函数,实现与isupper函数相同的功能。1、包含头文件#include 2、函数声明int isupper(int c);3、功能说明判断参数c是否为大写字母,您可能会问:isupper函数的参数是int c,是整数,不是字符,在C语言中,字符就是...

weixin_26704651的博客 891

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

实现c语言中的string.h头文件的部分函数

实现c语言中的string.h头文件的部分函数

qq_47500842的博客 411

c语言md5函数头文件,【C】md5函数实现代码

网上找到的md5函数的代码,试了一下,可以用,记录一下。包括三个文件,依次如下:头文件md5.h#ifndef MD5_H#define MD5_Htypedef struct{unsigned int count[2];unsigned int state[4];unsigned char buffer[64];}MD5_CTX;#define F(x,y,z) ((x & y) | (...

weixin_39783771的博客 689

手动实现的C语言string.h 头文件的字符串函数

研究C语言,首先要明白其库函数…001#include 002char* strcpy(char* dest,constchar* src);  //字符串拷贝 003char* strcat(char* dest,constchar* src);  //字符串连接,返回dest字符串 004char* strncat(char* dest, constchar* src, intsize);//把src前n个字符串连接到dest,返回dest字符串 005int   strcmp(constchar* s

qinqqfirst的专栏 1912

C语言-----string.h头文件中相关字符串函数的模拟实现

strlen:用途:Get the length of a string.函数原型:size_t strlen( const char *string ); size_t表示无符号的意思,长度值肯定是无符号的。模拟实现:int my_strlen(const char *str) { int count = 0; assert(str != NULL); while (*str != '\0...

abc_xixi111的博客 1419

[deepseek] C语言头文件与汇编实现讨论

这个表记录了哪个目标文件提供了哪个符号(如 abc_asm.o 提供了 add_two_numbers),以及哪个目标文件需要哪个符号(如 main.o 需要 add_two_numbers)。他拿着工程师的设计图(main.o),看到上面需要一个工具,于是他去各个车间寻找,找到了贴着对应标签的工具(来自 abc_asm.o),然后把它们完美地组装在一起。他阅读了说明书,知道需要调用一个叫 add_two_numbers 的工具,并在他的设计图(main.o)上留下了安装这个工具的接口。

1808

c++ swap函数头文件_C语言自定义头文件

0.建立工程在建头文件之前,我们还是从建立一个C语言工程开始,所用工具:DEV C++ 第一步:文件 → 新建 → 项目图1 第二步:Basic → Empty Project 图2 第三步:选择路径(选择一个路径即可),保存之后就生成一个first.dev (工程文件)图3 第四步:保存之后,回到程序编辑界面,可以看到 first工程有一个未命名的编辑页面.图4 第五步:我们可以在这个页面写程...

weixin_39941732的博客 2810

【C语言】字符函数和字符串函数(1)

str是\0了,循环是照常结束,但是str还要++一次,str就指向\0后面了,根据我们前面的分析就是错误的,所以这里只能把str自增的语句写在循环体内,当然,如果是拷贝字符串则不用担心这一点,可以放心把自增写在循环判断条件中。原型解析:strcpy的第一个参数是我们拷贝字符串的目的地的首地址,也就是接收拷贝的数组的首元素地址,第二个参数是我们拷贝字符串的源字符串的首地址,它的返回值就是接收拷贝的目标空间的初始地址。strcmp的作用就是帮我们比较两个字符串的大小,那么比较的依据是什么呢?

hdxbufcbjuhg的博客 2269

listlength函数头文件_数据结构----头文件实现顺序表的创建、(c语言)小结

#include #include "mytest.h"void main(){test = 25;printf("test=%d\n",test);}mytest.h头文件内容如下:#ifndef _MYTEST_H_#define _MYTEST_H_int test;#endif现在用上面的例子来说下解VC编译器的工作:1.预处理阶段:编译器以.cpp文件作为一个单元,首先读这个文件,发现前...

weixin_39621427的博客 1015

使用stdarg.h头文件实现参数数量可变函数【C语言】

介绍使用stdarg.h头文件实现参数数量可变函数的步骤。

qq_45965652的博客 216

c语言自定义status头文件,如何自定义C语言.h头文件?

在项目实践中,如果一个.c文件程序过长,可以把文件中的函数单独放在一个头文件中,然后在.c中包含该头文件即可。这两天,根据所看的书《C语言的科学与艺术》和网上的资料,发现实际上有两种写法。写法1:在.h头文件中就包含函数的实现,这种头文件实际上是把函数放在一起,便于管理而已。这种情况下只有一个.h文件。写法2:在.h头文件中只包含一些函数的声明,没有具体的实现。函数的实现放在另外一个不包含main...

weixin_39838362的博客 2546

如何自定义C语言.h头文件?

在项目实践中,如果一个.c文件程序过长,可以把文件中的函数单独放在一个头文件中,然后在.c中包含该头文件即可。这两天,根据所看的书《C语言的科学与艺术》和网上的资料,发现实际上有两种写法。 写法1:在.h头文件中就包含函数的实现,这种头文件实际上是把函数放在一起,便于管理而已。这种情况下只有一个.h文件。 写法2:在.h头文件中只包含一些函数的声明,没有具体的实现。函数的实现放在另外一...

吉大秦少游 5万+

c语言中自定义h文件路径,如何自定义C语言.h头文件?

在项目实践中,如果一个.c文件程序过长,可以把文件中的函数单独放在一个头文件中,然后在.c中包含该头文件即可。这两天,根据所看的书《C语言的科学与艺术》和网上的资料,发现实际上有两种写法。写法1:在.h头文件中就包含函数的实现,这种头文件实际上是把函数放在一起,便于管理而已。这种情况下只有一个.h文件。写法2:在.h头文件中只包含一些函数的声明,没有具体的实现。函数的实现放在另外一个不包含main...

weixin_39725756的博客 1749
上一篇: C语言库函数大全(字母a)---使用说明(转)
下一篇: Super日语在线背诵 - 沪江网
mlxia
博客等级 码龄26年 28粉丝 410原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值