非典型性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

相关文章

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

java.sql.SQLTransientConnectionException连接超时异常原因及解决方案

《java.sql.SQLTransientConnectionException连接超时异常原因及解决方案》:本文主要介绍java.sql.SQLTransientConnectionExcep... 目录一、引言二、异常信息分析三、可能的原因3.1 连接池配置不合理3.2 数据库负载过高3.3 连接泄漏

基于C#实现PDF转图片的详细教程

《基于C#实现PDF转图片的详细教程》在数字化办公场景中,PDF文件的可视化处理需求日益增长,本文将围绕Spire.PDFfor.NET这一工具,详解如何通过C#将PDF转换为JPG、PNG等主流图片... 目录引言一、组件部署二、快速入门:PDF 转图片的核心 C# 代码三、分辨率设置 - 清晰度的决定因

GO语言短变量声明的实现示例

《GO语言短变量声明的实现示例》在Go语言中,短变量声明是一种简洁的变量声明方式,使用:=运算符,可以自动推断变量类型,下面就来具体介绍一下如何使用,感兴趣的可以了解一下... 目录基本语法功能特点与var的区别适用场景注意事项基本语法variableName := value功能特点1、自动类型推

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

Java Scanner类解析与实战教程

《JavaScanner类解析与实战教程》JavaScanner类(java.util包)是文本输入解析工具,支持基本类型和字符串读取,基于Readable接口与正则分隔符实现,适用于控制台、文件输... 目录一、核心设计与工作原理1.底层依赖2.解析机制A.核心逻辑基于分隔符(delimiter)和模式匹

Mac电脑如何通过 IntelliJ IDEA 远程连接 MySQL

《Mac电脑如何通过IntelliJIDEA远程连接MySQL》本文详解Mac通过IntelliJIDEA远程连接MySQL的步骤,本文通过图文并茂的形式给大家介绍的非常详细,感兴趣的朋友跟... 目录MAC电脑通过 IntelliJ IDEA 远程连接 mysql 的详细教程一、前缀条件确认二、打开 ID

spring AMQP代码生成rabbitmq的exchange and queue教程

《springAMQP代码生成rabbitmq的exchangeandqueue教程》使用SpringAMQP代码直接创建RabbitMQexchange和queue,并确保绑定关系自动成立,简... 目录spring AMQP代码生成rabbitmq的exchange and 编程queue执行结果总结s

Go语言连接MySQL数据库执行基本的增删改查

《Go语言连接MySQL数据库执行基本的增删改查》在后端开发中,MySQL是最常用的关系型数据库之一,本文主要为大家详细介绍了如何使用Go连接MySQL数据库并执行基本的增删改查吧... 目录Go语言连接mysql数据库准备工作安装 MySQL 驱动代码实现运行结果注意事项Go语言执行基本的增删改查准备工作

Go语言使用Gin处理路由参数和查询参数

《Go语言使用Gin处理路由参数和查询参数》在WebAPI开发中,处理路由参数(PathParameter)和查询参数(QueryParameter)是非常常见的需求,下面我们就来看看Go语言... 目录一、路由参数 vs 查询参数二、Gin 获取路由参数和查询参数三、示例代码四、运行与测试1. 测试编程路