我们在工作中经常会看到xx.a和xx.so这样的文件,那么这是什么呢?又有什么作用呢?这篇我们就可以很好的认识并熟练的使用他们。
点开这首音乐,我们开始进入正题。
一、c语言编译流程
- 预处理
- 编译
- 汇编
- 链接
我们知道c语言编译器gcc,那么我们下面就看下gcc的主要语法,如下:
man gcc我们可以知道
-E:Preprocess only; do not compile, assemble or link;只预处理,不会编译、汇编、链接
-S:Compile only; do not assemble or link;只编译,不会汇编、链接
-c:Compile and assemble, but do not link; 编译和汇编,不会链接
-o<file>:Place the output into <file>;指定输出文件名为file
-v:查看gcc编译器的版本,显示gcc执行时的详细过程
# 源文件是hell.c 预处理:gcc hello.c -E -o hello.i 编译:gcc hello.i -S -o hello.s 汇编:gcc hello.s -c -o hello.o 链接:gcc hello.o -o hello
预处理、编译、汇编、链接
预处理阶段:
预处理:头文件包含、宏替换、条件编译
编译阶段:
编译生成的汇编代码
汇编阶段:
汇编代码转换机器码,这个阶段我们就不考虑了。
链接阶段:
动态链接或者静态链接生成可执行程序
二、动态链接与静态链接
静态链接是由链接器在链接时将库的内容加入到可执行程序中的做法。链接器是一个独立程序,将一个或多个库或目标文件(先前由编译器或汇编器生成)链接到一块生成可执行程序。静态链接是指把要调用的函数或者过程链接到可执行文件中,成为可执行文件的一部分。
动态链接所调用的函数代码并没有被拷贝到应用程序的可执行文件中去,而是仅仅在其中加入了所调用函数的描述信息(往往是一些重定位信息)。仅当应用程序被装入内存开始运行时,在Windows的管理下,才在应用程序与相应的DLL之间建立链接关系。当要执行所调用DLL中的函数时,根据链接产生的重定位信息,Windows才转去执行DLL中相应的函数代码。
静态链接、动态链接
三、静态库与动态库制作
# hello.c hello.h test.c test.h # hello.c #include<stdio.h> #include"hello.h" #include"test.h" #define M #ifdef M #define N 50 #if N>20 void hell(){ printf("hello\n"); } #else #define n 20 #endif #endif int main(){ test(); test1(); hell(); printf("hello world:%d %d\n",N,a); return 0; } #hello.h int a = 666; #test.c #include<stdio.h> #include"test.h" void test(){ printf("hello\n"); } void test1(){ printf("hello\n"); } #test.h void test(); void test1();
制作:
# 生成test.o gcc -c test.c ar -cr libtest1.a test.o #静态库制作 gcc -shared -fpic -o libtest2.so test.c #动态库制作 gcc -o hello hello.c -L. -ltest1 gcc -o hello hello.c -static -L. -ltest1 gcc -o hello hello.c -L. -ltest2 gcc -o hello hello.c -static -L. -ltest2 #错误
这里发现了动态生成的文件的确比较小。静态库支持动态链接和静态链接?动态库只支持默认的动态链接?
test@DESKTOP-AR8TSM0:~$ ll libtest1.a libtest2.so -rw-rw-r-- 1 test test 1832 Mar 25 18:07 libtest1.a -rwxrwxr-x 1 test test 7928 Mar 25 18:14 libtest2.so* #这里看出来动态库比静态库大