首页 GCC基础
文章
取消

GCC基础

GCC基础

GCC处理流程

.h 或 .c 或 .cpp 通过预处理器得到预处理后的源代码 .i

.i 通过编译器得到汇编代码 .s

.s 通过汇编器得到目标代码 .o

.o 通过链接器得到可执行文件 .exe 或 .out

gcc-1

实例

1
2
3
4
5
6
7
gcc test.c -E -o test.i 注意-o指的是生成输出文件 后面的是输出文件名称
这里生成了预处理后的源代码
gcc test.i -S -o test.s
这里生成了汇编代码
gcc test.s -s -o test.o  注意这里是小s
这里生成了目标代码
如果test.c没有用到外部文件可以直接执行.o

gcc-2

静态库

命名规则:

  1. Linux: libxxx.a

lib前缀是固定的

xxx是名字

.a后缀固定

  1. Windows: libxxx.lib

静态库制作

  1. gcc获得 .o 文件

    1
    
    gcc -c xxx.c xxx.c
    
  2. .o 文件打包,使用ar工具

    1
    2
    3
    4
    
    ar rcs libxxx.a xxx.o xxx.o
    r - 将文件插入备存文件中
    c - 建立备存文件
    s - 索引
    

QQ截图20220519231928

静态库特点:

静态库优点:

  1. 静态库被打包到应用程序中加载速度快。
  2. 发布程序无需提供静态库, 移植性好

静态库缺点:

  1. 消耗系统资源,浪费空间和内存。因为函数相关的所有的库都被打包进可执行文件了。
  2. 更新,发布,部署较为麻烦。更新以后需要重新编译:库是被复制到可执行文件中去了,如果某个库更新了,则与它相关的所有可执行文件都需要重新编译。

静态库对函数库的链接是放在编译时期完成的。

动态库

命名规则

  1. Linux: libxxx.so

    lib前缀是固定的

    xxx是名字

    .so后缀固定

    在linux下是一个可执行文件

  2. Windows: libxxx.dll

动态库制作

  1. gcc得到 .o 文件,需要添加 -fpic 或 -fPIC 参数得到和位置无关的代码

    1
    
    gcc -c -fpic/-fPIC xxx.c xxx.c
    
  2. gcc 得到动态库

    1
    
    gcc -shared xxx.o xxx.o -o libxxx.so
    

注意事项

在include的头文件路径和执行文件不一致的时候需要加上 -I参数指定头文件目录

在动态库的路径和执行文件路径不一致的时候需要加上-L参数指定动态库文件目录

动态库存在需要设置环境变量的情况。这里不赘述

QQ截图20220519232007

使用示范

动态库静态库相同

1
2
3
假设路径不同
gcc 执行文件名 -o 输出文件名 -I 头文件目录 -L 动态库目录 -l 动态库名称 注意不是文件名称是动态库名称
gcc main.c -o main -I ./include/ -L ./lib/ -l calc

动态库特点:

动态库优点:

  1. 动态库只有一份, 可以实现进程间资源共享(共享库)。
  2. 更新,部署,发布简单。
  3. 可以控制何时加载动态库。(可以在链接载入时完全由程序员在程序代码中控制。)

动态库缺点:

  1. 加载速度比静态库慢。
  2. 发布程序时需要提供依赖的动态库。

动态库把对一些库函数的链接载入推迟到程序运行的时期。

区别与联系

二者的不同点在于代码被载入的时刻不同。 静态库的代码在编译过程中已经被载入可执行程序,因此体积比较大。 动态库(共享库)的代码在可执行程序运行时才载入内存,在编译过程中仅简单的引用,因此代码体积比较小。

不同的应用程序如果调用相同的库,那么在内存中只需要有一份该动态库(共享库)的实例。 静态库和动态库的最大区别,静态情况下,把库直接加载到程序中,而动态库链接的时候,它只是保留接口,将动态库与程序代码独立,这样就可以提高代码的可复用度,和降低程序的耦合度。 静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。 动态库在程序编译时并不会被连接到目标代码中,而是在程序运行时才被载入,因此在程序运行时还需要动态库存在。

本文由作者按照 CC BY 4.0 进行授权