gcc命令解析及应用

前言

我们通常把一些公用函数制作成函数库,供其它程序使用。函数库分为静态库和动态库两种。
静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。
本文主要通过举例来说明在Linux 中如何创建静态库和动态库,以及使用它们。


一、用gcc生成静态库和动态库

1.准备工作

(1)创建一个目录;
(2)编写代码;
hello.h

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

hello.c

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

main.c

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

(3)将hello.c 编译成.o 文件;

gcc -c hello.c

在这里插入图片描述

2.由.o 文件创建静态库

(1)创建静态库
创建静态库的工具:ar
静态库文件命名规范:以lib作为前缀,是.a文件;

ar -crv libmyhello.a hello.o

在这里插入图片描述
(2)程序中使用静态库
①gcc -o hello main.c -L. -lmyhello;
在这里插入图片描述
②gcc main.c libmyhello.a -o hello;
在这里插入图片描述
③先生成main.o gcc -c main.c
生成可执行文件 gcc -o hello main.c libmyhello.a;
在这里插入图片描述

3.由.o 文件创建动态库文件

(1). 创建动态库
创建动态库的工具:gcc
动态库文件命名规范:以lib作为前缀,是.so文件;

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

在这里插入图片描述
(2). 在程序中执行动态库
gcc -o hello main.c -L. -lmyhello或gcc main.c libmyhello.so -o hello
再运行可执行文件hello,会出现错误;
在这里插入图片描述
问题的解决方法:将libmyhello.so复制到目录/usr/lib中;

sudo mv libmyhello.so /usr/lib

在这里插入图片描述

二、静态库.a与.so库文件的生成与使用

2.1编写代码

A1.c

#include<stdio.h>
void print1(int arg)
{
	printf("A1 print arg:%d\n",arg);
}

A2.c

#include<stdio.h>
void print2(char *arg)
{
	printf("A2 printf arg:%s\n",arg);
}

A.h

#ifndef A_H
#define A_H
void print1(int);
void print2(char *);
#endif

test.c

#include<stdio.h>
#include"A.h"
int main()
{
	print1(1);
	print2("test");
	return 0;
}

2.1静态库.a 文件的生成与使用

在这里插入图片描述

2.2共享库.so 文件的生成与使用

在这里插入图片描述

三、实例练习

准备工作:
在这里插入图片描述

3.1代码

sub1.c

float x2x(int a,int b)
{
	float c=0;
	c=a+b;
	return c;
}

sub2.c

float x2y(int a,int b)
{
	float c=0;
	c=a/b;
	return c;
}

sub.h

#ifndef SUB_H
#define SUB_H
float x2x(int a,int b);
float x2y(int a,int b);
#endif

main.c

#include<stdio.h>
#include"sub.h"
void main()
{
	int a,b;
	printf("Please input the value of a:");
	scanf("%d",&a);
	printf("Please input the value of b:");
	scanf("%d",&b);
	printf("a+b=%.2f\n",x2x(a,b));
	printf("a/b=%.2f\n",x2y(a,b));
}

3.2生成静态库

gcc -c sub1.c sub2.c 
ar crv libsub.a sub1.o sub2.o
gcc -o main main.c libsub.a

在这里插入图片描述

3.3生成动态库

在这里插入图片描述

四、Linux GCC 常用命令

4.1简单编译

代码:

//test.c
#include <stdio.h>
int main(void)
{
printf("Hello World!\n");
return 0;
}

预处理:

gcc test.c -o test

编译为汇编代码:

gcc -S test.i -o test.s

汇编:

gcc -c test.s -o test.o

连接:

gcc test.o -o test

在这里插入图片描述
多个程序文件的编译:
假设有一个由 test1.c 和 test2.c 两个源文件组成的程序,为了对它们进行编译,并
最终生成可执行程序 test,可以使用下面这条命令:

gcc test1.c test2.c -o test

五、GCC 编译器背后的故事

5.1GCC

GCC( GNU C Compiler) 是 编 译 工 具 。 本 文 所 要 介 绍 的 将 C/C++语 言 编 写 的 程 序
转 换 成 为 处 理 器 能 够 执 行 的 二 进 制 代 码 的 过 程 即 由 编 译 器 完 成 。

5.2Binutils

一 组 二 进 制 程 序 处 理 工 具 ,包 括 :addr2line、ar、objcopy、objdump、as 、ld、
ldd 、 readelf 、 size 等 。 这 一 组 工 具 是 开 发 和 调 试 不 可 缺 少 的 工 具 , 分 别 简 介
如 下 :
(1) addr2line : 用 来 将 程 序 地 址 转 换 成 其 所 对 应 的 程 序 源 文 件 及 所 对 应 的 代 码
行 ,也 可 以 得 到 所 对 应 的 函 数 。该 工 具 将 帮 助 调 试 器 在 调 试 的 过 程 中 定 位 对
应 的 源 代 码 位 置 。
(2) as:主要用于汇编 。
(3) ld:主要用于链接 。
(4) ar:主要用于创建静态库 。
(5) ldd:可以用 查看一个可执行程序依赖的共享库 。
(6) objcopy:将一种对象文件翻译成另一种格式,譬如将.bin转换成.elf、或者将 .elf转换成.bin 等。
(7) objdump: 主 要 的 作 用 是 反 汇 编 。
(8) readelf: 显 示 有 关 ELF 文 件 的 信 息 ,
(9) size: 列 出 可 执 行 文 件 每 个 部 分 的 尺 寸 和 总 尺 寸 , 代 码 段 、 数 据 段 、 总 大 小
等 。

5.3C运行库

C 语 言 标 准 主 要 由 两 部 分 组 成 : 一 部 分 描 述 C 的 语 法 , 另 一 部 分 描 述 C 标 准 库 。
C 标 准 库 定 义 了 一 组 标 准 头 文 件 ,每 个 头 文 件 中 包 含 一 些 相 关 的 函 数 、变 量 、类
型 声 明 和 宏 定 义 , 譬 如 常 见 的 printf 函 数 便 是 一 个 C 标 准 库 函 数 , 其 原 型 定 义
在 stdio 头 文 件 中 。
C 语 言 标 准 仅 仅 定 义 了 C 标 准 库 函 数 原 型 , 并 没 有 提 供 实 现 。 因 此 , C 语 言 编 译
器 通 常 需 要 一 个 C 运 行 时 库 ( C Run Time Libray, CRT) 的 支 持 。 C 运 行 时 库 又
常 简 称 为 C 运 行 库 。 与 C 语言类 似 , C++也 定 义 了 自 己 的 标 准 , 同 时 提 供 相 关 支
持 库 , 称 为 C++运 行时库 。


总结

通过本次实验,在ubuntu中进行各种命令操作,了解了gcc命令并非一个人在战斗,它同样需要其他工具进行辅助。熟练掌握了使用gcc命令生成静态库和动态库,也认识到了静态库与动态库的区别。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值