当前位置:   article > 正文

【C语言】GCC相关常识

【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
    
    • 1
  2. 编译

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

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

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

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

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

gcc main.o -o main

#查看main文件信息
file main
  • 1
  • 2
  • 3
  • 4

3. 静态库和动态库

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

其中文件file1.c 如下:

#include"head.h"

int sum(int a, int b)
{
        return a+b;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

其中文件file2.c 如下:

#include"head.h"

int mul(int a,int b)
{
        return a*b;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

其中文件head.h如下:

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

其中调用文件 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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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
    
    • 1
    • 2
  • 步骤2:使用打包工具 ar 将准备好的 .o 文件打包为 .a 文件

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

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

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

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

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

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

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

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

  生成 hello 可执行文件

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

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
    
    • 1
    • 2
  • 步骤2:生成动态库,添加参数 -share ,意思是生成动态库

    gcc -shared file1.o file2.o -o libhello.so
    
    • 1
  • 步骤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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

最后

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/623578
推荐阅读
相关标签
  

闽ICP备14008679号