C语言 超详细讲解链接器
什么是链接器
在C语言编写代码时,我们往往需要调用一些库函数,比如printf
、malloc
等等。这些库函数在我们的代码文件中并没有实现,而是存储在系统或其他库文件中,我们需要通过链接器把这些函数与我们编写的代码组合在一起,生成可执行程序。
链接器主要负责以下两个任务:
- 符号解析:将目标文件中引用的符号与定义的符号建立联系。
- 符号重定位:将目标文件中引用的符号地址引用替换为实际的地址。
静态链接
静态链接是将所有目标文件和库文件的编译结果一起链接成一个独立的可执行文件。这样生成的可执行文件包含了所有代码和数据,以及被程序引用的库函数和操作系统函数。
静态链接的过程:
1. 预处理目标文件:将源代码预处理成为独立的*.o
目标文件。
gcc -c a.c -o a.o
- 预处理库文件:将需要的库文件进行预处理,生成库目标文件。
gcc -c lib.c -o lib.o
- 静态链接:
gcc a.o lib.o -o prog
- 运行可执行文件:
./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
- 创建共享库:将编译生成的
*.o
目标文件生成共享连接库。其中,Linux 需要将后缀.so
,链接库标记添加--shared
,Windows 需要将后缀.dll
,链接库标记添加/DLL
。
gcc -shared lib.c -o lib.so
- 动态链接可执行文件:
gcc -o prog a.o -L. -l:lib.so
- 运行可执行文件
./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技术站