GCC 编译链接与执行

  本文介绍GCC的编译链接与执行,下面是编译链接常用到的参数及其描述:

参数描述
-c 编译、汇编指定的源文件(也就是编译源文件),但是不进行链接
-o用来指定输出文件
-L为 gcc 增加一个搜索链接库的目录
-l用来指定程序要链接的库

0.静态连接库和动态链接库的区别

  静态库和动态库最本质的区别就是:该库是否被编译进目标(程序)内部。

0.1静态(函数)库

  一般扩展名为.a.lib,这类的函数库通常扩展名为libxxx.axxx.lib

  这类库在编译的时候会直接整合到目标程序中,所以利用静态函数库编译成的文件会比较大,这类函数库最大的优点就是编译成功的可执行文件可以独立运行,而不再需要向外部要求读取函数库的内容;但是从升级难易度来看明显没有优势,如果函数库更新,需要重新编译。

0.2动态函数库

  动态函数库的扩展名一般为.so.dll,这类函数库通常名为libxxx.soxxx.dll

  与静态函数库被整个捕捉到程序中不同,动态函数库在编译的时候,在程序里只有一个“指向”的位置而已,也就是说当可执行文件需要使用到函数库的机制时,程序才会去读取函数库来使用;也就是说可执行文件无法单独运行。这样从产品功能升级角度方便升级,只要替换对应动态库即可,不必重新编译整个可执行文件。

1.主程序的编译、链接与执行

  在代码目录下编写main.c文件,功能是输出字符串Hello Cacu!,内容如下:

#include <stdio.h>

int main(void)
{
    printf("Hello Cacu!\n");
    return 0;
}

使用gcc -c main.c命令进行编译,发现目录想生成了一个main.o文件,如下:
在这里插入图片描述

通过 file 命令查看 main.o 的文件格式:
在这里插入图片描述

这说明 main.o 实际上是一个relocatable object 文件。通过以下命令为 main.o 文件赋予可执行的权限:

chmod 777 main.o

输入以下命令尝试执行 main.o 文件:

./main.o

Terminal 输出可执行文件格式错误,如图所示:
在这里插入图片描述
说明 relocatable object 文件是不可执行的。
接下来通过 GCC 对main.o 文件进行链接操作,从而生成一个可执行的程序 main

在 Terminal 中输入以下命令将 main.o 链接为 main 文件:

gcc -o main main.o

可以发现当前目录新增了一个名为 main 的文件。
在这里插入图片描述

通过 file 命令查看 main 的文件格式:

file main

输出结果如图所示:
在这里插入图片描述
说明 main 文件是一个可执行的文件,于是通过以下命令来执行 main 文件:

./main

输出结果如图所示:
在这里插入图片描述
说明程序得到了正确的执行。

2.静态链接

  编写 add_minus.h 文件,在文件中对函数 add()minus() 进行声明。编写 add_minus.c 文件,实现函数 add()minus()

#ifndef __ADD_MINUS_H__
#define __ADD_MINUS_H__

int add(int a, int b);
int minus(int a, int b);

#endif /*__ADD_MINUS_H__*/
#include "add_minus.h"

int add(int a, int b)
{
    return a+b;
}

int minus(int a, int b)
{
    return a-b;
}

add_minus.c 文件进行编译,生成 add_minus.o 文件。

gcc -c add_minus.c

修改 main.c 文件,为其增加加减法运算并编译这个文件。

#include <stdio.h>
#include "add_minus.h"

int main(void)
{
	int rst;

    printf("Hello Cacu!\n");

	rst = add(3,2);
	printf("3 + 2 = %d\n",rst);

	rst = minus(3,2);
	printf("3 - 2 = %d\n",rst);

    return 0;
}

通过以下命令对 main.c 文件进行编译和链接:

gcc -c main.c
gcc -o main main.o

链接生成的 main.o 文件时,发现有错误出现,错误内容如图所示:
在这里插入图片描述

原因在于链接过程中找不到 addminus 这两个 symbol。现将 main.oadd_minus.o 链接成可执行文件并执行测试。

gcc -o main main.o add_minus.o

执行新生成的可执行文件 main

./main

在这里插入图片描述

重新编译 add_minus.c 生成 add_minus.o 文件。

gcc -c add_minus.c

通过 ar 命令将 add_minus.o打包到静态库中。

ar rc libadd_minus.a add_minus.o

可以发现在当前目录下,生成了一个名为 libadd_minus.a 的静态库文件
在这里插入图片描述
file 命令查看 libadd_minus.a 的文件格式。

file libadd_minus.a

Terminal 输出结果如图所示:
在这里插入图片描述

实际上 libxxx.a 格式的文件可以简单的看成指定的以 .o 结尾的文件集合。

链接 main.o 和静态库文件:

gcc -o main2 main.o -L./ -ladd_minus
  • -L./:表明库文件位置在当前文件夹。

  • -ladd_minus:表示链接 libadd_minus.a 文件,使用 -l 参数时,前缀 lib 和后缀 .a 是需要省略的。

执行 main2:

./main2

Terminal 输出结果如图所示,说明程序的到了正确的执行。
在这里插入图片描述

3.动态链接

  编写 multi_div.h 文件,并在其中对函数 multi()div() 进行声明。编写 multi_div.c 文件,实现函数 multi()div()

#ifndef __MULTI_DIV_H__
#define __MULTI_DIV_H__

int multi(int a, int b);
int div(int a, int b);

#endif /*__MULTI_DIV_H__*/
#include "multi_div.h"

int multi(int a, int b)
{
    return a*b;
}

int div(int a, int b)
{
    return a/b;
}

通过以下命令将 multi_div.c 文件编译成动态链接库。

gcc multi_div.c -fPIC -shared -o libmulti_div.so
  • -fPIC 选项作用于编译阶段,在生成目标文件时就得使用该选项,以生成位置无关的代码。
    命令执行结束后,在当前目录下会生成一个名为 libmulti_div.so 的文件。

在这里插入图片描述

通过 file 命令来查看 libmulti_div.so 的文件格式。

file libmulti_div.so

Terminal 输出结果如图所示:
在这里插入图片描述
由此可知 libmulti_div.so 是一个 shared object 文件。

编写main.c文件如下:

#include <stdio.h>
/*
#include "add_minus.h"
*/
#include "multi_div.h"

int main(void)
{
    int rst;

    printf("Hello Cacu!\n");
/*
    rst = add(3,2);
    printf("3 + 2 = %d\n",rst);

    rst = minus(3,2);
    printf("3 - 2 = %d\n",rst);
*/
    rst = multi(3,2);
    printf("3 * 2 = %d\n",rst);

    rst = div(6,2);
    printf("6 / 2 = %d\n",rst);

    return 0;
}

编译 main.c 生成 main.o

gcc -c main.c

链接 main.o 与动态链接库文件:

gcc -o main3 main.o -L./ -lmulti_div

执行生成的 main3 文件:

./main3

输出结果出现错误,如图所示:
在这里插入图片描述

出现错误的原因是我们生成的动态库 libmulti_div.so 并不在库文件搜索路径中。
解决办法:将 libmulti_div.so 拷贝到/lib//usr/lib/ 文件夹下。

sudo cp libmulti_div.so /usr/lib

现在在 Terminal 中执行下面的命令:

./main3

在这里插入图片描述
说明程序得到了正确的执行。

4.混合使用静态链接与动态链接

  编写新的main.c程序如下,仍然调用前面章节使用的add_minus.hadd_minus.cmulti_div.hmulti_div.c文件。

#include <stdio.h>
#include "add_minus.h"
#include "multi_div.h"

int main(void)
{
	int rst;

    printf("Hello Cacu!\n");
	
	rst = add(3,2);
	printf("3 + 2 = %d\n",rst);

	rst = minus(3,2);
	printf("3 - 2 = %d\n",rst);

	rst = multi(3,2);
	printf("3 * 2 = %d\n",rst);

	rst = div(6,2);
	printf("6 / 2 = %d\n",rst);

    return 0;
}

编译 main.c 生成 main.o

gcc -c main.c

测试执行混用静态链接和动态链接的方式。

gcc -o main4 main.o -L./ -ladd_minus -lmulti_div

执行下面的命令:

./main4

输出结果如图所示:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI Chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值