Linux下gcc生成静态库.a和动态库.so

目录

程序例子

1.编辑生成例子程序 hello.h、hello.c 和 main.c。

hello.c

 #include <stdio.h> 
 void hello(const char *name) 
 {
 printf("Hello %s!\n", name);
  }

hello.h

#ifndef HELLO_H 
#define HELLO_H 
void hello(const char *name); 
#endif //HELLO_H

main.c

#include "hello.h" 
int main() 
{
hello("everyone"); 
return 0; 
}

2.将 hello.c 编译成.o 文件

gcc -c hello.c

观察编译结果:
在这里插入图片描述

3.由.o 文件创建静态库。

静态库文件名的命名规范是以 lib 为前缀,紧接着跟静态库名,扩展名为.a。创建静态库用 ar 命令。在系统提示符下键入以下命令将创建静态库文件 libmyhello.a。

ar -crv libmyhello.a hello.o

输入ls观察结果
在这里插入图片描述

4.在程序中使用静态库。

方法一:

gcc -o hello main.c -L. –lmyhello

-L. 表示要连接的库在当前目录中;
-lmyhello编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上 lib,后面 加上.so 或.a 来确定库的名称 libmyhello.so 或 libmyhello.a。
方法二:

gcc main.c libmyhello.a -o hello

(ps:个人推荐第二种方法,但是第一中更能体现出库的链接)
观察结果:
在这里插入图片描述
我们删除一下libmyhello.a文件试一下程序是否能进行
在这里插入图片描述
可以得出静态库的链接是将整个库和目标文件打包在一起的。

5.由.o 文件创建动态库文件。

动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀 lib,但其 文件扩展名为.so。
输入下面的代码:

gcc -shared -fPIC -o libmyhello.so hello.o 

-shared 该选项指定生成动态连接库,不用该标志外部程序无法连接。相当于一个可执行文件。
-fPIC作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

观察结果:
在这里插入图片描述

6.在程序中使用动态库。

建立执行文件与链接静态库相似,输入以下代码:

gcc -o hello main.c -L. -lmyhello

或者

gcc main.c libmyhello.so -o hello

执行结果:
注意:因为虽然连接时用的是当前目录的动态库,但是运行时,是到 /usr/lib 中找库文件的,将文件 libmyhello.so 移动到目录/usr/lib 中就 OK 了,注意先sudo su,不然权限不够。
在这里插入图片描述

7.当静态库和动态库同名时,gcc 命令会使用哪个库文件呢?

在这里插入图片描述
输入执行文件时,结果与使用动态库的结果相同(出现了同样的错误),可以看出当静态库和动态库同名时,gcc 命令会优先使用动态库文件。

程序实践

1.生成.c文件

main1.c

#include<stdio.h>
#include"sub1.h"
#include"sub2.h"
void main()
{
 int a,b,c;
a=10;b=8;
 c=x2x(a,b);
printf("x2x=%d\n",c);
printf("x2y=%d\n",x2y(a,b)); 
}

sub1.c

#include<stdio.h>
int x2x(int a,int b)
{
   int c;
   c=a*b;
return c;
}

sub1.h

int x2x(int a,int b);

sub2.c

#include<stdio.h>
int x2y(int a,int b)
{
printf("hello world!\n");
return (a+b);
}  

sub2.h

int x2y(int a,int b);

2.生成静态库.a和动态库.so

生成.a文件:
通过gcc将sub1.c,sub2.c编译成.o文件后,输入代码:

ar -cr libhehe.a sub1.o sub2.o

生成.so文件:

gcc -shared -fPIC -o libhehe.so sub1.o sub2.o

结果如图:
在这里插入图片描述

3.动态库和静态库的运用

1.静态库
输入:

gcc main1.c libhehe.a -o qwe1

执行结果:
在这里插入图片描述
文件大小

在这里插入图片描述

2.动态库
输入:

gcc main1.c libhehe.so -o qwe2

执行结果:
在这里插入图片描述
文件大小:
在这里插入图片描述
对比文件差异不大,可能是因为生成.o文件很小,导致生成的两个库文件都很小,差异就很小。
要想观察静态库和动态库文件大小的差异怎么办呢?
用ldd观察链接的动态库是,发现还链接了一个动态库
在这里插入图片描述
在gcc 里面加入参数static把动态库连接转变成静态库连接
在这里插入图片描述
发现调用静态库方式比动态库所需要的空间更大。

总结:

本次的学习,了解了静态库与动态库的区别,静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。在实践中,由于本人代码水平有限,如果有什么出错的地方,希望能交流,互相促进提高

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值