【C语言】GCC相关常识

GCC相关常识

1. GCC、gcc 编译器、g++编译器

  GCC原名为GNU C语言编译器(GNU C Compiler),只能处理C语言。但其很快扩展,变得可处理C++,后来又扩展为能够支持更多编程语言,如Fortran、Pascal、Objective -C、Java、Ada、Go以及各类处理器架构上的汇编语言等,所以改名GNU编译器套件(GNU Compiler Collection)来自百度百科

  gcc 是 GNU 的c编译器,是GNU编译器套件GCC(GNU Compiler Collection)的其中一个。

   g++ 是 GNU 的c++编译器,是GNU编译器套件GCC(GNU Compiler Collection)的其中一个。

  gcc 和 g++ 在编译的时候有一些区别,但是大体流程类似。

2. gcc 、g++ 编译流程

在 gcc 或 g++ 执行编译的时候一般有 以下4步:

  1. 预处理

      处理源代码文件中的预处理指令,另外将 main.c 文件生成 main.i 文件

    gcc -E main.c -o main.i
    
  2. 编译

      将预处理后的源代码转换为汇编语言。将main.i 文件生成 main.s 汇编文件,注意这里是大写S,十分重要。

    gcc -S main.i -o main.s
    
  3. 汇编

      将汇编代码转换成机器码。main.s 文件转换成 main.o 文件

    gcc -c main.s -o main.o
    
  4. 链接

  合并所有的汇编文件,然后生成一个ELF类型的可执行文件main

gcc main.o -o main

#查看main文件信息
file main

3. 静态库和动态库

  库文件是源文件的一种存在形式,库文件又分为静态库和动态库。下面使用4个文件 file1.c、file2.c、head.h、hello.c 进行动态库和静态库制作和使用的演示。

其中文件file1.c 如下:

#include"head.h"

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

其中文件file2.c 如下:

#include"head.h"

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

其中文件head.h如下:

#include<stdio.h>
int sum(int a,int b);
int mul(int a,int b);

其中调用文件 hello.c 如下:

#include"head.h"

int main()
{
        printf("1+2=%d\n",sum(1,2));
        printf("2*2=%d\n",mul(2,2));
        return 0;
}

3.1 静态库

  静态库最终被打包到应用程序中,优点是速度快,方便移植,缺点是每个进程使用应用程序时都要拷贝一份静态库,浪费内存,而且静态库更新时,程序都要重新编译,导致用户的整个程序都要重新下载。

  静态库的命名一般分为三个部分:

  • 后缀为 .a

  • 库名称 可以 自定义,例如hello

  • 前缀为 lib

    例如一个名为 hello 的静态库 为 libhello.a

静态库的制作和使用

  使用 file1.c、file2.c制作静态库,其中 head.h 文件中有函数的声明,file1.c 和 file2.c 有函数的实现,最后使用 hello.c 去链接静态库文件。

  • 步骤1:将 .c 源文件 汇编生成 .o 文件

    gcc -c file1.c -o file1.o
    gcc -c file2.c -o file2.o
    
  • 步骤2:使用打包工具 ar 将准备好的 .o 文件打包为 .a 文件

    其中,ar工具可以添加 参数 r 更新 、c 创建、s建立索引

    #生成静态库 libhello.a
    ar rcs libhello.a file1.o file2.o
    

    静态库制作完成,使用时,需要结合头文件 head.h 和 libhello.a

  • 步骤3:使用静态库,需要一些参数进行描述

    -L:大诶儿,指定要连接的库所在目录

    -l:小诶儿,指定链接时需要的静态库,去除前缀和后缀,例如:-lhello

    -I:大哎,指定 hello.c 文件用到的头文件 head.h 所在的路径

    gcc -o hello hello.c -L./ -lhello -I./
    

  生成 hello 可执行文件

#执行
./hello
#输出
1+2=3
2*2=4

3.2 动态库

  共享库在程序编译时不会连接到程序中,只有程序运行时才会被载入。不同程序调用相同的库,内存中只有一份共享库的拷贝。当动态库更新时,只需要跟新动态库这一个部分。优点是节省内存,更新方便。缺点是移植性差,加载速度比静态库慢。

  动态库的命名一般分为三个部分:

  • 后缀为 .so

  • 库名称 可以 自定义,例如hello

  • 前缀为 lib

    例如一个名为 hello 的动态库 为 libhello.so

动态库的制作和使用

  使用 file1.c、file2.c 制作动态库,其中 head.h 文件中有函数的声明,file1.c 和 file2.c 有函数的实现,最后使用 hello.c 去链接动态库文件。

  • 步骤1:将 .c 源文件 汇编生成 .o 文件

    其中 -fpic 参数是指创建与地址无关的编译程序 ( pic,position independent code)

    gcc -fpic -c file1.c -o file1.o
    gcc -fpic -c file2.c -o file2.o
    
  • 步骤2:生成动态库,添加参数 -share ,意思是生成动态库

    gcc -shared file1.o file2.o -o libhello.so
    
  • 步骤3:动态库使用,需要一些参数进行描述

    -L:大诶儿,指定要连接动态库的所在目录

    -l:小诶儿,去掉前缀后缀的指定动态库的名称,例如 -lhello

    -I:大哎,指定 hello.c 用到的头文件 head.h 所在的路径

gcc hello.c -L./ -I./ -lhello -o hello

#此时会报错,因为找不到 libhello.so 库,报错信息:
./hello: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory
#原因是系统加载动态库时是从默认的动态库地址开始找起

#查看可执行文件依赖的库文件
ldd hello
#输出,其中 libhello.so => not found
linux-vdso.so.1 (0x00007ffec773b000)
	libhello.so => not found
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4820e2f000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f4821220000)
	
#解决方法有:
#1.将动态库拷贝到系统默认的动态库地址,通常是 /lib 或者 /usr/lib

#2.临时设置动态库地址
#export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./

#3.永久设置动态库地址
#3.1
#把export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径,设置到/etc/profile文件中
#执行source /etc/profile 使配置文件生效
#3.2
#把export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径, 设置到∼/.bashrc文件中
#source ~/.bashrc 使配置文件生效


#这里是演示,所以我使用临时设置动态库地址
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./
./hello
#输出
1+2=3
2*2=4

最后

推荐一个零声教育学习教程,个人觉得老师讲得不错,分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:链接

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值