非典型性C语言教程- 0.4 连接

2024-02-08 05:18

本文主要是介绍非典型性C语言教程- 0.4 连接,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

0.2 里面说过,当你使用gcc -o hello hello.c 时,gcc实际是先调用cpp预处理hello.c中的预处理命令,再自己编译之,最后调用ld进行连接生成可执行文件。Windows下是cl.exe 和link.exe。

用- c选项可以让编译器不连接,如 gcc -c hello.c,或是cl -c hello.c 这样会只将源文件编译成目标文件。Unix下叫hello.o,Windows下叫hello.obj。目标文件是不能执行的,但是目标文件中已经是可以 执行的机器指令了。其实目标文件和最后生成的可执行文件一样,都是一组函数(函数就是一段一段的机器指令),两者的区别在于目标文件中对函数的调用都是按 名字调用的,而可执行程序中已经是按地址调用了。先举例子,比如hello.c 程序中调用了printf("hello.c");。编译成的目标文件中,会有一个符号表,其中有一个符号叫printf,并且表明他是一个函数。但是由 于这个函数实际在标准库中,所以还不知道这个函数的具体细节,只有符号在那里。Hello world例子中,自己写的只有一个源文件,编译之后只需要与C语言的标准库连接就可以。

C语言的标准库实际就是一组函数。在 Windows下你安装了VC或是VS会给你安装上,在%VCHOME%/lib目录下,叫msvcrt.lib。这个lib文件实际使用的是% Windows%/system32下的msvcrt.dll。在Unix下在/usr/lib下,一般叫libc.so或是glibc.so等名字。C 语言的标准库基本上是操作系统不可缺少的部分。

首先生成hello.o或是hello.lib文件, 然后编译器调用ld或是link.exe将目标文件与C语言的标准库连接。连接在一起的时候,就可以决定, 每个函数的地址。比如main函数在0x400008出,prinft在0x400030 出。然后开始resovle符号。发现hello.o中有一个函数叫main,main中有一个对printf函数的调用,而C语言的标准库中的符号表中 有一个printf的函数,于是main中对printf的函数调用就转到标准库中printf函数的入口去了,函数调用就被翻译成一条汇编指令比如叫 call 0x400030了。最后会给程序加上一段stratup代码,这段代码完成一些初始化工作比如读参数,共享文件表等等,然后调用查找叫main的函数, 调用main。连接的过程就完成了。

当程序大的时候,需要多个源文件。会产生多个目标文件,可能目标文件a调用了目标文件b内的函数,这 些最后都是在连接的时候resolve的。还是先举例子,比如有两个文件hello.c和foo.c,那么编译的时候可以写成gcc -o hello hello.c foo.c,但是实际上编译器是这样作的,

gcc -c hello.c
gcc -c foo.c
ld -0 hello hello.o foo.o
上面3行命令的意义应该很清楚。

下面说说连接时容易产生的问题:
  1. unresolved symbol:这个问题一般是忘了连接某个库,或是连接某个目标文件造成的。
  2. 符号已定义,或是符号冲突:这个问题一般是有函数或变量重名造成的。
连接时候产生的错误并不报告是那个文件那一行错了,找起来会很麻烦。一般要用文件搜索找到相应的符号在那里。 

这篇关于非典型性C语言教程- 0.4 连接的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/690002

相关文章

MySQL 多表连接操作方法(INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL OUTER JOIN)

《MySQL多表连接操作方法(INNERJOIN、LEFTJOIN、RIGHTJOIN、FULLOUTERJOIN)》多表连接是一种将两个或多个表中的数据组合在一起的SQL操作,通过连接,... 目录一、 什么是多表连接?二、 mysql 支持的连接类型三、 多表连接的语法四、实战示例 数据准备五、连接的性

MySQL中的分组和多表连接详解

《MySQL中的分组和多表连接详解》:本文主要介绍MySQL中的分组和多表连接的相关操作,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录mysql中的分组和多表连接一、MySQL的分组(group javascriptby )二、多表连接(表连接会产生大量的数据垃圾)MySQL中的

springboot使用Scheduling实现动态增删启停定时任务教程

《springboot使用Scheduling实现动态增删启停定时任务教程》:本文主要介绍springboot使用Scheduling实现动态增删启停定时任务教程,具有很好的参考价值,希望对大家有... 目录1、配置定时任务需要的线程池2、创建ScheduledFuture的包装类3、注册定时任务,增加、删

C语言中位操作的实际应用举例

《C语言中位操作的实际应用举例》:本文主要介绍C语言中位操作的实际应用,总结了位操作的使用场景,并指出了需要注意的问题,如可读性、平台依赖性和溢出风险,文中通过代码介绍的非常详细,需要的朋友可以参... 目录1. 嵌入式系统与硬件寄存器操作2. 网络协议解析3. 图像处理与颜色编码4. 高效处理布尔标志集合

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

如何为Yarn配置国内源的详细教程

《如何为Yarn配置国内源的详细教程》在使用Yarn进行项目开发时,由于网络原因,直接使用官方源可能会导致下载速度慢或连接失败,配置国内源可以显著提高包的下载速度和稳定性,本文将详细介绍如何为Yarn... 目录一、查询当前使用的镜像源二、设置国内源1. 设置为淘宝镜像源2. 设置为其他国内源三、还原为官方

C 语言中enum枚举的定义和使用小结

《C语言中enum枚举的定义和使用小结》在C语言里,enum(枚举)是一种用户自定义的数据类型,它能够让你创建一组具名的整数常量,下面我会从定义、使用、特性等方面详细介绍enum,感兴趣的朋友一起看... 目录1、引言2、基本定义3、定义枚举变量4、自定义枚举常量的值5、枚举与switch语句结合使用6、枚

Maven的使用和配置国内源的保姆级教程

《Maven的使用和配置国内源的保姆级教程》Maven是⼀个项目管理工具,基于POM(ProjectObjectModel,项目对象模型)的概念,Maven可以通过一小段描述信息来管理项目的构建,报告... 目录1. 什么是Maven?2.创建⼀个Maven项目3.Maven 核心功能4.使用Maven H

IDEA自动生成注释模板的配置教程

《IDEA自动生成注释模板的配置教程》本文介绍了如何在IntelliJIDEA中配置类和方法的注释模板,包括自动生成项目名称、包名、日期和时间等内容,以及如何定制参数和返回值的注释格式,需要的朋友可以... 目录项目场景配置方法类注释模板定义类开头的注释步骤类注释效果方法注释模板定义方法开头的注释步骤方法注

Python虚拟环境终极(含PyCharm的使用教程)

《Python虚拟环境终极(含PyCharm的使用教程)》:本文主要介绍Python虚拟环境终极(含PyCharm的使用教程),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录一、为什么需要虚拟环境?二、虚拟环境创建方式对比三、命令行创建虚拟环境(venv)3.1 基础命令3