静态链接库

article/2025/9/29 9:11:05

库的存在,大大方便了我们进行编程。因为有了库,我们不必再从0开始,例如我们大多数人C语言写的第一个程序Hello World!都是用了库函数。以printf为例,我们只需要在程序源代码中包含<stdio.h>这个头文件之后,就可以使用printf函数了。这极大的方便了编程。同时库所带来的好处在于,头文件和库文件相结合的访问机制。有时候我们只想让别人使用自己实现的功能,并不想公开实现功能的源码,就可以将其制作为库文件,这样用户获取到的是二进制文件,而头文件又只包含声明部分,这样就实现了“将源码隐藏起来”的目的,且不会影响用户使用。

库文件用于程序的链接阶段,但编译器提供有 2 种实现链接的方式,分别是静态链接方式和动态链接方式,其中采用静态链接方式实现链接操作的库文件,称为静态链接库;采用动态链接方式实现链接操作的库文件,称为动态链接库。本文将介绍静态链接库。

静态链接库简介

静态链接库实现链接操作的方式很简单,即程序文件中哪里用到了库文件中的功能模块,GCC 编译器就会将该模板代码直接复制到程序文件的适当位置,最终生成可执行文件。显然,这种方式带来的优势生成的可执行文件不再需要任何静态库文件就可以独立运行;但是这个优点也会带来一些缺点,那就是生成的可执行文件体积会很大。在Linux下静态库的一般以后缀.a结尾,在Windows下一般以.lib结尾。

静态链接库创建

现在假设,我的项目拥有helloworld_c.c,helloworld_c.h两个文件。它们的内容分别如下所示。

helloworld_c.h文件

#ifndef HELLOWORLD_C_H
#define HELLOWORLD_C_H#include <stdio.h>#ifdef __cplusplus     //使用__cplusplus宏配合extern "C"来告诉C++链接器,这是一个C接口。extern "C"{
#endifvoid Print_HelloWorld();#ifdef __cplusplus
}
#endif#endif //HELLOWORLD_C_H

该文件为了使得C++程序也能使用C写的库文件,使用了extern "C"的方式来包括头文件,原理详见C++调用C动态链接库

helloworld_c.c文件

#include"helloworld_c.h"void Print_HelloWorld()
{printf("Hello World!\n");
}

现在,我们来生成静态链接库。首先编译源文件生成相应的目标文件。

gcc -Wall -c helloworld_c.c

执行上面的命令之后,会生成一个名为helloworld_c.o的文件,现在使用 ar 压缩指令,将生成的目标文件打包成静态链接库。

ar rcs libhello.a helloworld_c.o

参数r:在库中插入模块(替换)。当插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其他同名模块。默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置。 

参数c:创建一个库。不管库是否存在,都将创建。 

参数s:创建目标文件索引,这在创建较大的库时能加快时间。(补充:如果不需要创建索引,可改成大写S参数;如果。a文件缺少索引,可以使用ranlib命令添加)

同时,需要注意,库的名字不能随便起。需要遵循规则libxxx.a

静态链接库使用

下面使用该静态链接库,在main.c文件中包含helloworld_c.h文件,即可使用Print_HelloWorld()函数。

#include"helloworld_c.h"int main()
{Print_HelloWorld();return 0;
}

使用静态链接库可以有下面两种方式。 

  1. 直接在GCC参数里加上-static和相应的静态链接库即可。-static表示强制 GCC 编译器使用静态链接库
    gcc -Wall -static main.c libhello.a
    即可链接libhello.a库文件,生成可执行文件a.out,执行a.out效果如下所示。

    可以看到成功打印了Hello World!
  2. GCC选项里加上-L和-l。-L(大写的 L)选项用于向 GCC 编译器指明静态链接库的存储位置; -l(小写的 L)选项用于指明所需静态链接库的名称,注意这里的名称指的是 xxx 部分,且建议将 -l 和 xxx 直接连用(即 -lxxx),中间不需有空格。
    gcc -Wall -static main.c -L. -lhello

    上述两种方式中,我们更常用的可能是第二种。

生成了可执行的a.out文件其实非常大,我们来看看它的大小。


http://chatgpt.dhexx.cn/article/I1IwOK3g.shtml

相关文章

史上最全Java类型转换

讲类型转换之前&#xff0c;让我来贴张表 基本数据类型的表示范围 类型 长度 表示范围默认值byte8b-128&#xff5e;1270short16b-32768&#xff5e;327670int32b-21147483648&#xff5e;21474836470long64b-9223372036 854 775 808&#xff5e;9223372036 8547758070Lfloat3…

Java:类型转换

public class Demo04 {public static void main(String[] args) {//低--------------------------> 高// byte,short,char->int->long->float->doubleint i 128;byte b (byte) i ;//内存溢出//强制转换 &#xff08;类型&#xff09;变量名 高--低//自动转换…

java强转规则_java类型转换及其规则介绍

一、自动类型转换 整型、实型(常量)、字符型数据可以混合运算。运算中&#xff0c;不同类型的数据先转化为同一类型&#xff0c;然后进行运算。 数据类型转换必须满足如下规则&#xff1a; 1、不能对boolean类型进行类型转换。 2、不能把对象类型转换成不相关类的对象。 3、在把…

Sql-Java类型转换

Mysql-Java字段类型转换 mysql类型名大小用途对应Java类char0-255 bytes定长字符串 &#xff08;姓名、性别、学号&#xff09;Stringvarchar0-65535 bytes变长字符串&#xff08;比上面更长一点的那种&#xff09;Stringtinytext0-255 bytes比较短的那种文本数据&#xff08;…

JAVA类型转换及变量详解

类型转换 由于java是强类型语言&#xff0c;所以要进行有些运算的时候&#xff0c;需要用到类型转换。 byte&#xff08;1个字节&#xff09;,short&#xff08;2个字节&#xff09;,char&#xff08;2个字节&#xff09;----->int&#xff08;4个字节&#xff09;---->…

Java类型转换(自动类型转换+强制类型转换)

一、 自动类型转换(隐式类型转换) 整型、实型(常量)、字符型数据可以混合运算。运算中,不同类型的数据先转化为同一类型,然后进行运算。自动转换从低级到高级。 自动转换有以下规律: 1、小的类型自动转化为大的类型 2、整数类型可以自动转化为浮点类型,可能会产生舍入误…

Java的类型转换

需要类型转换的原因:因为Java是强类型的语言&#xff0c;所以有时可能要进行跨类型的运算&#xff0c;这就需要先进行类型转换&#xff0c;再进行运算。 类型转换分为&#xff1a; 强制类型转换(由高-->低时使用)&#xff0c;自动类型转换/ 隐式类型转换(由低-->高时使用…

java中的类型转换

java的基本数据类型 1.数值型&#xff1a;byte&#xff0c;short&#xff0c;int&#xff0c;long&#xff0c;float&#xff0c;double 2.字符型&#xff1a;char 3.布尔型&#xff1a;boolean 数据类型占据字节数byte1个字节short2个字节int4个字节long8个字节float4个字节…

Java中各种类型的转化

目录 一.Integer和int之间的类型转化 1.自动装箱 2.构造器方法 3.Integer.valueOf(int i) 二.Integer和String之间的类型转换 1.String转换为Integer 1.Integer.parseInt(String s) ​编辑 2.Integer.valueOf(String s) 2.Integer转换为String 1.Integer.toString() …

【JAVA】Java中的类型转换

目录 1.自动类型转换&#xff08;隐式转换&#xff0c;小类型转换为大类型&#xff09; 2.强制类型转换&#xff08;显示转换&#xff0c;大类型转换为小类型&#xff09; 3.小于4字节的类型转换问题 3.1 byte<->int 3.2 char<->int 3.3 String<->int …

Java 类型转换

一、自动类型转换(隐式类型转换) 整型、实型(常量)、字符型数据可以混合运算。不同类型的数据先转化为同类型再进行运算 自动转换按从低级到高级顺序: char ↓ Byte→short→int→long---›float→double 自动转换有以下规律&#xff1a; 小的类型自动转化为大的类型 整数…

java类型转换

文章目录 1、什么是类型转换&#xff1f; 2、掌握常见数据类型的范围大小 3、自动类型转换 3.1 int转换为double 3.2 char转换为int类型 4、强制类型转换 4.1、强制类型转换格式 5、注意事项 1、什么是类型转换&#xff1f; 在java中类型转换是一个非常重要的知识点。因…

java中常见类型的转换以及方法总结

1.char、String、int类型之间的转换 1.1 char和String的区别 char是表示的是字符&#xff0c;定义的时候用单引号&#xff0c;只能存储一个字符。例如; char‘d’. String表示的是字符串&#xff0c;定义的时候用双引号&#xff0c;可以存储一个或者多个字符。例如&#xff1…

CentOs 无法启动网络,用ip addr看不到IP地址

1.无法启动网卡&#xff0c;启动报file exist 原因1&#xff1a;可能是别的网络与网络冲突 解决&#xff1a;关闭NetworkManager 原因2&#xff1a;etc/sysconfig/network-scripts下的ifcfg开头的文件有内容有冲突 解决&#xff1a;删除一些对应文件 如果还是不行&#xf…

ip命令的使用方式(临时设定:ip addr ,ifconfig)

对外开放&#xff0c;能和主机直接进行交流的设备叫做网卡 内部交流&#xff0c;系统内部服务与服务之间的接口&#xff0c;为回环接口 lo##回环设备 [rootlocalhost 桌面]# ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default…

ifconfig、ip addr、ip route用法总结

最近使用haproxykeepalived 负载均衡&#xff0c;发现虚拟IP有问题&#xff0c;配置文件里配的VIP是.4.143 ,但是执行 ip a 发现还有一个虚拟IP.4.134&#xff1b;应该是以前配置文件keepalived.conf里设置过VIP .4.134 以前的VIP一直没有消除&#xff0c;手动清除VIP&#xff…

Centos7中查看IP命令:IP addr

开机&#xff0c;输入用户名root和上篇文章中设置的密码&#xff0c;&#xff08;密码在Linux中是看不见的&#xff0c;但确实已经输入了&#xff09;&#xff0c;回车确定&#xff0c;显示时间信息&#xff08;没有设置时间&#xff09;&#xff0c;表示登陆成功。 在Centos7中…

openEuler 知:ip addr 查不到 ip 的解决方法

通过 VMware Workstation 安装 openEuler 虚拟机后&#xff0c;通过 ip addr 查不到 ip&#xff0c;如下所示&#xff1a; 备注&#xff1a;默认没有安装 ifconfig 命令。 解决方法&#xff1a; 进入 /etc/sysconfig/network-scripts 目录&#xff0c;在文件路径下找到 ifcf…

【Linux命令】ifconfig、route、ip route、ip addr、 ip link 用法 一

文章目录 1. 前言2. ifconfig2.1 配置地址2.2 查看功能2.2.1 ifconfig 查看不含禁用的网卡2.2.2 ifconfig -a 查看含禁用的网卡2.2.3 ip a 2.3 启用、禁用网卡2.3.1 ifconfig eth1 up、 ifconfig eth1 down2.3.2 ifdown eth0、ifip eth0 2.4 扫描eth0接口的数据2.5 网卡别名2.5…

docker exec -it tomcat01 ip addr

在学习狂神的docker内容网络学习这一步的时候&#xff0c;按照步骤启动tomcat镜像&#xff0c;但是执行ip addr 之后发现下面问题&#xff0c; 经过分析这说明我们下载的Tomcat镜像是精简版的&#xff0c;利用这个镜像去打开一个容器的时候发现没有ip addr这个命令。所以到导致…