关闭

关于在头文件中实现函数的情况

631人阅读 评论(0) 收藏 举报
分类:
下面举个例子,这个例子只有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 -c fun.c

$gcc -c main.c

$gcc -o main main.c fun.c

则会在链接是时候报重复定义base()的错误!

fun.o: In function `base':
fun.c:(.text+0x0): multiple definition of `base'
main.o:main.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit statu

注:开始时在对这行忽然很陌生,main.c中的fun(); 突然搞不清这行代码做了什么事了!fun的函数体是调用base()方法,虽然fun是在fun.c中实现的,但在main.c文件中用,

应该是调用main.c中的base()还是fun.c中的base()呢?其实,链接器自己都搞不清清楚了,所以报错了!


这里我突然想到一个问题:如在main中调用strlen(),但是编译的时侯,仅仅编译test.c,$gcc test.c即可!不需要编译strlen所在的.c文件吗?这个该怎么解释呢?

是不是这样的,这些标准函数已经编译成了动态链接库,程序编译后,直接链接就可以!但是,是通过什么样的方法找到对应的动态链接库文件呢?

对比自己写的函数API怎么才能像系统的strlen()一样呢?直接编译调用函数的那个文件?(待补充。欢迎赐教....)


对于上面的程序,如果这样编译

$gcc -c fun.c

$gcc -o main main.c

则报没有定义fun的错误;

/tmp/ccRYqwWl.o: In function `main':
main.c:(.text+0xc): undefined reference to `fun'        //未定义引用到‘fun’,因为fun.h中的fun();仅是声明!
collect2: error: ld returned 1 exit status,


---------------------------------------------------------------------------------------

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

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

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








0
0
猜你在找
【直播】机器学习&数据挖掘7周实训--韦玮
【套餐】系统集成项目管理工程师顺利通关--徐朋
【直播】3小时掌握Docker最佳实战-徐西宁
【套餐】机器学习系列套餐(算法+实战)--唐宇迪
【直播】计算机视觉原理及实战--屈教授
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之矩阵--黄博士
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之凸优化--马博士
【套餐】Javascript 设计模式实战--曾亮
查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:24219次
    • 积分:462
    • 等级:
    • 排名:千里之外
    • 原创:23篇
    • 转载:16篇
    • 译文:0篇
    • 评论:0条