编译和链接

//jia.h

int jia(int a,int b);


//jia.c

int jia(int a,int b)
{
        return a+b;
}

//test.c

#include<stdio.h>
#include "jia.h"

int main()
{
      printf("%d\n",jia(1,1));
}

用gcc命令编译test.c(单独用gcc编译一个文件,默认包含了链接的过程,如果只想编译,而不链接,要加-c参数)

gcc test.c

会出现如下错误

/tmp/ccBJQ1Z1.o: In function `main':
test.c:(.text+0x19): undefined reference to `jia'
collect2: error: ld returned 1 exit status

可以发现是错误的引用,连接器ld出错,因为没有找到函数jia的实现文件,需要指出的是#include仅仅添加了一个函数的声明,关于jia的实现,编译器不知道任何信息,因此要手动给出链接信息,正确的做法是,分别编译test.c和jia.c,然后把生成的两个目标文件链接起来。

gcc -c test.c
gcc -c jia.c
gcc test.o jia.o -o test


以下部分转载自http://www.cnblogs.com/webcyz/archive/2012/09/16/2688035.html

要理解头文件,主要是要理解“声明”
C/C++中,所有使用到得变量、函数、类都要是声明过得,就是说,要有一行语句来告诉编译器,我有一个名字叫XXX的???类型的变量(函数、类)。
然后还有一个因素就是,在编译的时候,程序是按照每个.C或.CPP文件单独编译的。
也就是说,对于每个C文件中,如果都用到了同一个函数(比如printf),那么,我在每个对应文件中写一遍printf的声明明显是很麻烦的。所以我把这个声明单独写了一个文件,为了区别,我把扩展名记做.h,在需要使用对应的函数(类)的时候,我就不需要去拷贝函数的声明,而只需要#include对应头文件就可以了,系统自动帮你拷贝进来——C语言提供的头文件,按照函数功能分类好了,比如数学函数就都写在了math.h里面,一包含就全包含,不管你用没用到cos()这个函数或者其他什么。
当然,由于.h文件中也可以包含其他.h文件,所以为了不重复声明或定义,需要用宏做相应的处理,这个不是要理解的东西,而是照着写。


编译的时候,gcc做的比我们想得多得多(包括了链接),想查看gcc都做了什么,添加-v选项,而ld命令仅仅是链接,它不知到main为入口点。

gcc -v -o test test.c



通常编译器并不要求函数一定要在被调用之前定义,编译器在处理到某个未知类型的函数时,会为其创建一个隐式声明,并假设该函数返回值类型为int。但编译器无法检查传递给该函数的实参类型和个数是否正确,所以这不利于编译器为我们排除错误。而且在VC编译器下,这样的代码会编译出错,一般可能提示“ error C2371: 'function1' : redefinition; different basic types”,因为编译器隐式声明了一个function1,VC编译器在后面遇到真实的function1定义时,真实的function1返回值并不是int,而是void。所以VC编译器认为function1函数重定义(redefinition)了。

C99遵循这样的规则:在调用一个函数之前,必须先对其进行声明或定义。调用函数时,如果此前编译器未见到该函数的声明或定义,会导致出错。”
所以,综上所述,尽管在gcc编译器中这样的代码仍然可以编译通过并且正确执行。也最好还是遵循这样的规则:在函数调用前,先对其定义或声明。

通过以上内容分析,我们可以知道,在调用一个函数之前,最好对其进行声明或者定义!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
在C++ 开发中,我们通常使用多个文件来编写大型程序,这使得代码更可维护且易于扩展。然而,当我们需要将这些文件组合在一起构建项目时,我们需要了解如何进行编译链接。 C++ 文件分为头文件和源文件。头文件通常包含类、函数和变量的声明,而源文件包含它们的实现。当一个源文件需要访问另一个源文件中的某些内容时,我们需要在头文件中声明它们,并在源文件中包含这些头文件。 下面是一个包含两个源文件的例子:main.cpp 和 myfunc.cpp。 main.cpp 包含一个 main() 函数,myfunc.cpp 包含一个名为 myfunc() 的函数。我们将在 main.cpp 中调用 myfunc()。 main.cpp: ```cpp #include <iostream> #include "myfunc.h" int main() { std::cout << myfunc() << std::endl; return 0; } ``` myfunc.cpp: ```cpp #include "myfunc.h" int myfunc() { return 42; } ``` myfunc.h: ```cpp #ifndef MYFUNC_H #define MYFUNC_H int myfunc(); #endif ``` 在上面的代码中,头文件 myfunc.h 包含了 myfunc() 函数的声明,在 main.cpp 中通过 #include "myfunc.h" 包含了这个头文件,使得 main.cpp 知道了 myfunc() 函数的存在。 接下来,我们需要编译链接这两个源文件,生成可执行文件。编译器将源文件转换为目标文件,并将目标文件链接成一个可执行文件。 我们需要使用以下步骤进行编译链接: 1. 将每个源文件编译成目标文件。在命令行中,我们可以使用以下命令来编译两个源文件: ``` g++ -c main.cpp -o main.o g++ -c myfunc.cpp -o myfunc.o ``` 上面的命令将 main.cpp 编译成 main.o 目标文件,将 myfunc.cpp 编译成 myfunc.o 目标文件。这些目标文件包含了源文件中定义的函数和变量的实现。 2. 将所有目标文件链接在一起,生成可执行文件。在命令行中,我们可以使用以下命令来链接两个目标文件: ``` g++ main.o myfunc.o -o myapp ``` 上面的命令将 main.o 和 myfunc.o 目标文件链接起来,生成一个名为 myapp 的可执行文件。 这样,我们就完成了 C++ 多文件编译链接的过程。在实际开发中,我们通常使用构建工具来自动化这些步骤,例如 Makefile 和 CMake。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值