【Linux】gcc/g++与动静态库

2023-12-13 03:41:46

目录

一、gcc和g++编译器的简单使用

1.1 编译C语言程序

1.2?编译C++语言程序

1.3 使用注意事项

二、gcc实现程序的翻译过程

2.1?预处理(进行宏替换)

2.2 编译(生成汇编)

2.3 汇编(生成机器可识别代码)

2.4 连接(生成可执行文件或库文件)

三、gcc的常用选项

四、函数库

4.1 库的概念

4.2 静态库与动态库

4.2.1 静态库

4.2.2 动态库

4.3 静态链接与动态链接

4.3.1 静态链接

4.3.2 动态链接

4.3.3?两者对比


一、gcc和g++编译器的简单使用

gcc和g++都是Linux系统下的编译器,其中gcc用于编译C语言程序,g++用于编译C++语言程序。
(g++也可以兼容编译C语言程序)

1.1 编译C语言程序

下面是使用gcc编译C语言程序的基本命令:

gcc [sourcefile.c] -o [outputfile]

其中'[sourcefile.c]'是要编译的C语言源代码文件,'-o'后面跟着想要生成的可执行文件的名称。

例如:gcc test.c -o test
这将会编译 'test.c' 并生成一个名为 'test' 的可执行文件。

1.2?编译C++语言程序

下面是使用g++编译C++语言程序的基本命令:

g++ [sourcefile.cpp] -o [outputfile]

其中 '[sourcefile.cpp]' 是要编译的C++源代码文件,'-o' 后面跟着想要生成的可执行文件的名称。

例如:g++ hello.cpp -o hello
这将会编译'hello.cpp'并生成一个名为'hello'的可执行文件。

1.3 使用注意事项

  • g++也可以兼容编译C语言程序,但gcc不能编译C++程序。

  • 有时在使用gcc编译C时会报错:


  • 这时只需要在命令后面加上 '-std=c99' 或 '-std=gun99' 即可
    例如:gcc test.c -o test -std=c99

  • 如果你需要链接多个源文件,可以将它们一起编译:
    gcc file1.c file2.c -o outputfile
    g++ file1.cpp file2.cpp -o outputfile
  • C++源代码文件的常见后缀有'.cpp','.cc','.cxx',三种没有区别,只是使用习惯不同。
  • 没有安装g++,直接输入以下命令即可
    yum install gcc-c++
  • Linux系统中认为文件后缀没有意义(文件属性中第一列的第一个字符来区分文件的类型),但是gcc编译器认为后缀有意义

  • 生成可执行文件后,可以使用./命令来运行程序。

  • 除了基本命令外,gcc和g++还支持许多编译选项,可以通过'gcc --help'和'g++ --help'命令来查看。


二、gcc实现程序的翻译过程

在之前的学习中我们了解到程序的翻译过程包括:预处理阶段、编译阶段、汇编阶段、链接阶段。

gcc命令可以通过使用不同的选项来完成以上四个过程。

2.1?预处理(进行宏替换)

预处理功能主要包括头文件展开,宏替换,条件编译,去注释等。

-E只进行预处理,生成预处理后的代码到标准输出。
例如: gcc -E sourcefile.c -o output.i

  • 预处理指令是以#号开头的代码行。
  • 选项"-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。
  • 选项"-o”是指目标文件,".i”文件为已经过预处理的C原始程序。
  • 通过条件编译,可以实现对代码的动态裁剪。
    (有很多软件,都是同一种软件,但是功能却有差别,有的是收费的,有的是免费的。
    例如vs, xshell,idea,vmware等,有专业版和社区版)
    背后源代码只需要维护1份!
    ?

2.2 编译(生成汇编)

在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言

-S:只进行编译,生成汇编代码文件到当前目录。

例如:gcc -S outputfile.i -o outputfile.s

  • 用户可以使用"-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。

2.3 汇编(生成机器可识别代码)

汇编阶段是把编译阶段生成的".s”文件转成目标文件

-c:执行汇编并将结果输出到目标文件中。

例如:gcc -c outputfile.s -o outputfile.o

  • 默认情况下,gcc在进行编译时会自动调用汇编器,生成目标文件(.o文件)。

2.4 连接(生成可执行文件或库文件)

在成功编译之后,就进入了连接阶段。在连接阶段,默认情况下,直接调用 gcc在编译后自动调用链接器生成可执行文件。如果要生成库文件,可以使用-shared选项。

直接调用 gcc?

例如:gcc outputfile.o -o executable

注:

  • 以上命令中,sourcefile.c是源代码文件的名称,outputfile.i是预处理后的代码文件,outputfile.s是汇编代码文件,outputfile.o是目标文件,executable是最终生成的可执行文件。
  • 各过程选项可以简记为:ESc (对应键盘左上角的Esc键,只是第二位大写)
    各过程的结果可以记为:iso
  • 如果命令后面没有用 -o ,结果可能就会打印在显示屏上。?

三、gcc的常用选项

  • -E? ?只激活预处理,这个不生成文件,需要把它重定向到一个输出文件里面(配合-o使用)。
  • -S???编译到汇编语言不进行汇编和链接。
  • -c?? 编译到目标代码。
  • -o <file>??指定输出文件的名称。
  • -static? ?此选项对生成的文件采用静态链接。(需要安装静态库)
    ?gcc code.c –o code.s -static 静态链接会生成较多的重复代码。
  • -g? ?生成调试信息。GNU 调试器可利用该信息。
  • -shared?此选项将尽量使用动态库,所以生成文件比较小,但是需要系统由动态库。
  • -O<level>?编译器的优化选项的4个级别(0-3),-O0表示没有优化,-O1为缺省值,-O3优化级别最高。
  • -w??不生成任何警告信息。
  • -Wall 生成所有警告信息。
  • -std=<standard>:指定要遵循的 C 或 C++ 标准,如 -std=c99、-std=c++11 等。

四、函数库

4.1 库的概念

函数库(或称为库、库文件、库函数)是一组预先编写好的可重用代码集合,旨在提供特定功能的函数和工具。函数库通常包含了各种函数、类、数据结构等,可以用于解决特定问题或完成特定任务。

我们的代码 + 头文件 + 库 = 我们的可执行程序。

为了避免重复性的基础工作,一些人把对应的常用功能和资源集合在一起,编写相应的代码,以后人们只需要使用对应的代码即可,不用自己再写一份。所以我们现在所写的所有代码,都是站在巨人的肩膀上,已经有人给我们写好了对应的可以直接使用的函数了。

这批功能函数,是以库的方式呈现给我们的。

  • ldd指令可以用来查看一个可执行程序所依赖的第三方库。?
    ldd <可执行程序名>
  • Linux系统中已经提前安装了一批需要的头文件和库文件。(Linux下一切皆文件)
    其中头文件提供方法的声明库文件提供方法的实现。?
    安装即下载并拷贝头文件和库文件到开发环境的指定路径下。

库的命名规则:

? ? ? ? 例如上面的? libc.so.6

  • 以lib开头
  • .so表示库的类别---动态库,若是以.a结尾,表示静态库。
  • .6 表示库的版本
  • c 就是这个库的名字,即C标准库(去掉前缀后缀)

函数库的优点在于可以减少重复编写代码的工作量,提高开发效率。通过使用函数库,开发人员可以直接调用库中的函数,而无需从头开始编写相同的代码。函数库也经过充分测试和优化,可以提供性能良好且稳定可靠的功能。

4.2 静态库与动态库

函数库一般分为静态库和动态库两种。

4.2.1 静态库

  • 静态库是在编译链接时,把库文件的代码全部加入到可执行文件中,因此生成的文件比较大,但在运行时也就不再需要库文件了。每个使用该库的程序都会包含一份该库的代码。
  • 静态库的文件后缀名通常为 “.a”(archive),在编译时需要指定库的路径和名称。
  • 静态库在程序执行时不需要外部的库文件,因此可以更容易地在不同的环境中进行部署。

注:

????????默认情况下云服务器是没有安装c静态库的,只有动态库,
????????如果需要安装,可以使用: sudo yum install glibc-static
????????C++的静态库: sudo yum install -y libstdc++-static

4.2.2 动态库

  • 动态库在编译链接时并没有把库文件的代码加入到可执行文件中,而是在程序执行时由运行时链接文件加载库,被所有程序以链接的方式关联起来,这样可以节省系统的开销
  • 动态库一般后缀名为“.so”,如前面所述的 libc.so.6 就是动态库。
  • gcc 在编译时默认使用动态库。完成了链接之后,gcc 就可以生成可执行文件。
  • gcc默认生成的二进制程序,是动态链接的,这点可以通过 file 命令验证

4.3 静态链接与动态链接

4.3.1 静态链接

  • 在编译时将所有依赖的库的代码合并到最终的可执行文件中的过程叫做静态链接。
  • 静态链接会导致可执行文件的体积增大,因为它包含了所有库的代码。此外,如果库的更新或修复发布,需要重新编译和重新分发可执行文件。

4.3.2 动态链接

  • 在程序运行时将所需的共享库(动态库)加载到内存中,并将程序与这些库建立关联的过程叫做动态链接。
  • 在动态链接的情况下,可执行文件中只包含对动态库的引用,而不包含库的实际代码。当程序启动时,操作系统会在系统路径或指定的路径中搜索并加载所需的动态库。
  • 库中所有的函数,都有入口地址,所谓的动态链接,其实就是把要连接的库中的函数地址拷贝到我们的可执行程序的特定位置!

4.3.3?两者对比

动态链接:把要连接的库中的函数地址拷贝到可执行程序的特定位置
优点:体积小,节省磁盘空间,加载到内存,节省内存空间。
缺点:强依赖库(动态库没了,所有的依赖这个库的程序都无法运行了)

静态链接:把需要的代码拷贝到可执行程序中
优点:无视库,可以独立运行。
缺点:体积大,浪费资源。

文章来源:https://blog.csdn.net/muyuteacher/article/details/134849732
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。