C语言 超详细讲解链接器

C语言 超详细讲解链接器

什么是链接器

在C语言编写代码时,我们往往需要调用一些库函数,比如printfmalloc等等。这些库函数在我们的代码文件中并没有实现,而是存储在系统或其他库文件中,我们需要通过链接器把这些函数与我们编写的代码组合在一起,生成可执行程序。

链接器主要负责以下两个任务:
- 符号解析:将目标文件中引用的符号与定义的符号建立联系。
- 符号重定位:将目标文件中引用的符号地址引用替换为实际的地址。

静态链接

静态链接是将所有目标文件和库文件的编译结果一起链接成一个独立的可执行文件。这样生成的可执行文件包含了所有代码和数据,以及被程序引用的库函数和操作系统函数。

静态链接的过程:
1. 预处理目标文件:将源代码预处理成为独立的*.o目标文件。

gcc -c a.c -o a.o
  1. 预处理库文件:将需要的库文件进行预处理,生成库目标文件。
gcc -c lib.c -o lib.o
  1. 静态链接:
gcc a.o lib.o -o prog
  1. 运行可执行文件:
./prog

示例1:工程调用printf函数

main.c文件如下:

#include <stdio.h>

int main()
{
    printf("Hello, world!\n");
    return 0;
}

编译过程:

gcc -o main main.c

执行结果:

Hello, world!

示例2:工程调用某个库函数

math.h头文件中包含了数学库函数sqrt的声明,我们可以通过链接数学库来使用这个函数。

main.c文件如下:

#include <stdio.h>
#include <math.h>

int main()
{
    double result = sqrt(2.0);
    printf("sqrt(2.0)=%f\n", result);
    return 0;
}

编译过程:

gcc -o main main.c -lm

-lm参数表示链接数学库。

执行结果:

sqrt(2.0)=1.414214

动态链接

动态链接是指在程序运行时才将程序需要的库文件动态链接到程序中。这样生成的可执行文件不包含库函数和操作系统函数的代码,而是在程序执行时才从动态库文件中加载。

动态链接的优点是可以减少可执行程序的大小,减少内存占用,但是需要一定的额外开销来加载动态链接库。

动态链接过程:
1. 预处理目标文件:同静态链接。

gcc -c a.c -o a.o
  1. 创建共享库:将编译生成的*.o目标文件生成共享连接库。其中,Linux 需要将后缀.so,链接库标记添加--shared,Windows 需要将后缀.dll,链接库标记添加/DLL
gcc -shared lib.c -o lib.so
  1. 动态链接可执行文件:
gcc -o prog a.o -L. -l:lib.so
  1. 运行可执行文件
./prog

示例3:工程调用共享库函数

shared_lib.c文件如下:

#include <stdio.h>

void show(int n)
{
    printf("show: %d\n", n);
}

编译成动态库:

gcc -shared shared_lib.c -o libshared_lib.so

Windows,编译成dll:

gcc -shared shared_lib.c -o shared_lib.dll

main.c文件如下:

#include <stdio.h>

void show(int);

int main()
{
    show(3);
    return 0;
}

编译动态链接版本可执行文件:

gcc -o dynamic main.c -L. -l:libshared_lib.so

Windows,编译dll:

gcc -o dynamic.exe main.c -L. -l:shared_lib.dll

执行结果:

show: 3

总结

链接器是任何编程语言工具链中都不可缺少的一环。静态链接和动态链接都是链接器的重要功能,对C语言程序的编译和运行有着至关重要的作用。对于理解代码模块化及整体编译过程更是有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言 超详细讲解链接器 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • Android的日志系统分层与logcat使用

    Android的日志系统分为四层,分别是: 核心层(kernel):负责底层的输入输出、内存、磁盘、进程等操作。本层日志主要是通过printk等函数输出,并存储在ring buffer中,只有在安卓手机发生严重错误时才需要查看。 系统层(system):包括system_server、Zygote和ActivityManager等系统服务,存放的是系统服务的…

    C 2023年5月24日
    00
  • C语言/C++中如何产生随机数

    产生随机数是计算机编程中常用的操作,C语言和C++编程语言也提供了产生随机数的函数。下面我将会详细讲解在C语言和C++编程语言中如何产生随机数。 在 C 语言中产生随机数 在C语言语言中,使用rand()函数可以产生随机数。这个函数的返回值是随机数。但是,如果不进行特别的设置,rand()函数每次返回的随机数都是相同的。这是因为随机数的生成是基于种子的。如果…

    C 2023年5月23日
    00
  • 使用批处理异地备份数据(winrar)

    下面我将详细讲解如何使用批处理异地备份数据(winrar)。 1. 准备工作 在使用批处理进行异地备份之前,需要先下载安装 WinRAR 软件,并确保已经设置好环境变量。同时需要确定好备份的目录和备份的目标路径。 2. 编写批处理脚本 我们可以使用 notepad 或者其他文本编辑器来编写批处理脚本。打开文本编辑器,输入如下代码: @echo off set…

    C 2023年5月22日
    00
  • 使用c语言输出杨辉三角形的简单方法

    要在C语言中输出杨辉三角形,可以使用嵌套循环结构和两个数组。下面是完整的攻略: 1. 定义两个数组 首先,我们需要定义两个一维数组。数组a将保存上一行的数值,数组b将用于保存当前行的数值。这样,我们就可以使用a数组中的数据来计算下一行,然后将b数组中的数据输出。 #include <stdio.h> int main() { int a[10],…

    C 2023年5月23日
    00
  • 结合Mybatis聊聊对SQL注入的见解

    结合MyBatis聊聊对SQL注入的见解 什么是SQL注入? SQL注入(SQL Injection),也称为SQL攻击,是一种代码注入攻击。攻击者利用Web应用程序通过将恶意的SQL代码注入到输入字段中来攻击后台数据库服务器,从而获得敏感信息或者完全控制后台数据库。这些注入代码可能在数据请求中或者输入URL参数中出现。SQL注入是当前Web应用程序的最大安…

    C 2023年5月22日
    00
  • 带你理解C语言中的汉诺塔公式

    下面是 “带你理解C语言中的汉诺塔公式” 的完整攻略: 1. 汉诺塔问题简介 汉诺塔问题是著名的递归问题。汉诺塔的玩具包括三个柱子和一些大小不同的盘子,开始时所有的盘子都按大小顺序堆叠在一个柱子上,目标是把它们移动到另一个柱子上,移动过程中要遵循以下规则: 每次只能移动一个盘子。 移动盘子时,只能把较小的盘子放在较大的盘子上面。 拿“汉诺塔问题”来说,假如有…

    C 2023年5月22日
    00
  • 关于Http持久连接和HttpClient连接池的深入理解

    关于Http持久连接和HttpClient连接池的深入理解 什么是Http持久连接 在Http1.0中,每次客户端想要请求内容时,都会和服务器建立一次连接,产生一次完整的Http事务。连接关闭后,所有的相关资源被释放。 在Http1.1中,为了提高效率,引入了持久连接,即同一个连接可以请求多个资源。所以,Http持久连接可以理解为,在同一个连接上可以发送多个…

    C 2023年5月22日
    00
  • json与jsonp知识小结(推荐)

    让我来为您详细讲解“json与jsonp知识小结(推荐)”的完整攻略。 1. 什么是 JSON JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,它基于 JavaScript的对象语法。它有如下几个特点: JSON是一种文本格式,可以轻松地在网络上传输。 JSON的语法和JavaScript的语法几乎相同,因此易读易…

    C 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部