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

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

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

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

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

  合并所有的汇编文件,然后生成一个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
目录
相关文章
|
3月前
|
NoSQL 编译器 程序员
【C语言】揭秘GCC:从平凡到卓越的编译艺术,一场代码与效率的激情碰撞,探索那些不为人知的秘密武器,让你的程序瞬间提速百倍!
【8月更文挑战第20天】GCC,GNU Compiler Collection,是GNU项目中的开源编译器集合,支持C、C++等多种语言。作为C语言程序员的重要工具,GCC具备跨平台性、高度可配置性及丰富的优化选项等特点。通过简单示例,如编译“Hello, GCC!”程序 (`gcc -o hello hello.c`),展示了GCC的基础用法及不同优化级别(`-O0`, `-O1`, `-O3`)对性能的影响。GCC还支持生成调试信息(`-g`),便于使用GDB等工具进行调试。尽管有如Microsoft Visual C++、Clang等竞品,GCC仍因其灵活性和强大的功能被广泛采用。
126 1
|
5月前
|
编译器 C语言
C语言编译详解:GCC分步编译与一次编译多个文件
C语言编译详解:GCC分步编译与一次编译多个文件
490 2
|
程序员 编译器 C语言
初识C语言(5)C语言一些基本常识
初识C语言(5)C语言一些基本常识
65 0
|
编译器 Linux API
一个问题引出的---对gcc与C语言标准思考
最近在总结关于Linux系统关于Time处理相关的API,当在开发库中使用到localtime_r以及clock_gettime时,会提示如下的错误(-Werror选项打开):
607 0
|
编译器 C语言 Windows
【C 语言】Windows 下使用 gcc 编译器 ( 常用的编译器 | Qt 中的 gcc 编译器 | 独立安装 MinGW )(三)
【C 语言】Windows 下使用 gcc 编译器 ( 常用的编译器 | Qt 中的 gcc 编译器 | 独立安装 MinGW )(三)
164 0
【C 语言】Windows 下使用 gcc 编译器 ( 常用的编译器 | Qt 中的 gcc 编译器 | 独立安装 MinGW )(三)
|
编译器 C语言 Windows
【C 语言】Windows 下使用 gcc 编译器 ( 常用的编译器 | Qt 中的 gcc 编译器 | 独立安装 MinGW )(二)
【C 语言】Windows 下使用 gcc 编译器 ( 常用的编译器 | Qt 中的 gcc 编译器 | 独立安装 MinGW )(二)
139 0
【C 语言】Windows 下使用 gcc 编译器 ( 常用的编译器 | Qt 中的 gcc 编译器 | 独立安装 MinGW )(二)
|
编译器 Linux C语言
【C 语言】Windows 下使用 gcc 编译器 ( 常用的编译器 | Qt 中的 gcc 编译器 | 独立安装 MinGW )(一)
【C 语言】Windows 下使用 gcc 编译器 ( 常用的编译器 | Qt 中的 gcc 编译器 | 独立安装 MinGW )(一)
405 0
【C 语言】Windows 下使用 gcc 编译器 ( 常用的编译器 | Qt 中的 gcc 编译器 | 独立安装 MinGW )(一)
|
C语言 芯片
使用 gcc 命令把C语言程序反汇编
之前看过一点汇编,不过现在都忘记得差不多了。最近又很蛋疼地想起反汇编这个东西。这里使用 gcc 命令对 .c 文件进行反汇编,把 C语言 翻译成汇编语言 先准备一个简单的 C 程序 sum.c #include int add(int, int); int mode(int, i...
3910 0
|
C语言 编译器 Linux
用gcc编译c语言程序以及其编译过程
对于初学c语言编程的我们来说,学会如何使用gcc编译器工具,对理解c语言的执行过程,加深对c语言的理解很重要!!! 1、预编译 --> 2、编译 --> 3、汇编 --> 4、链接----------------------------------------------------------------------------- 0、编写c代码,并输入以下如图代码,生成c文件hello.c。
1612 0