免责声明:本栏主要是对牛客视频学习的记录,方便以后自己复习。
1.什么是GCC?
- GCC 原名为 GNU C语言编译器(GNU C Compiler)
- GCC(GNU Compiler Collection,GNU编译器套件)是由 GNU 开发的编程语言 译器。GNU 编译器套件包括C、C++、Objective-C、Java、Ada 和 Go 语言前 端,也包括了这些语言的库(如 libstdc++,libgcj等)
- GCC 不仅支持 C 的许多“方言”,也可以区别不同的 C 语言标准;可以使用命令行 选项来控制编译器在翻译源代码时应该遵循哪个 C 标准。例如,当使用命令行参数
-std=c99
启动 GCC 时,编译器支持 C99 标准。
安装命令 sudo apt install gcc g++
查看版本 gcc/g++ -v/–version
GCC的工作流程
gcc 和 g++ 的区别
gcc 和 g++都是GNU(组织)的一个编译器。
误区一:gcc 只能编译 c 代码,g++ 只能编译 c++ 代码。两者都可以,请注意:
- 后缀为 .c 的,gcc 把它当作是 C 程序,而 g++ 当作是 c++ 程序
- 后缀为 .cpp 的,两者都会认为是 C++程序,C++ 的语法规则更加严谨一些
- 编译阶段,g++ 会调用 gcc,对于 C++ 代码,两者是等价的,但是因为 gcc命令不能自动和 C++ 程序使用的库联接,所以通常用 g++ 来完成链接,为了统 一起见,干脆编译/链接统统用 g++了,这就给人一种错觉,好像 cpp 程序只 能用 g++ 似的
误区二:gcc 不会定义 __cplusplus 宏,而 g++ 会
实际上,这个宏只是标志着编译器将会把代码按 C 还是 C++ 语法来解释
如上所述,如果后缀为 .c,并且采用 gcc编译器,则该宏就是未定义的,否则, 就是已定义
误区三:编译只能用 gcc,链接只能用 g++
严格来说,这句话不算错误,但是它混淆了概念,应该这样说:编译可以用gcc/g++,而链接可以用 g++ 或者 gcc -lstdc++。
gcc 命令不能自动和C++程序使用的库联接,所以通常使用 g++ 来完成联接。但在编译阶段,g++ 会自动调用 gcc,二者等价
GCC常用参数选项
2.静态库的制作与使用
- 库文件是计算机上的一类文件,可以简单的把库文件看成一种代码仓库,它提供给使用 者一些可以直接拿来用的变量、函数或类。
- 库是特殊的一种程序,编写库的程序和编写一般的程序区别不大,只是库不能单独运行。
- 库文件有两种,静态库和动态库(共享库),区别是:静态库在程序的链接阶段被复制到了程序中;动态库在链接阶段没有被复制到程序中,而是程序在运行时由系统动态加 载到内存中供程序调用。
- 库的好处:1.代码保密 2.方便部署和分发
命名规则:
Linux : libxxx.a
lib : 前缀(固定)
xxx : 库的名字,自己起
.a : 后缀(固定)
Windows : libxxx.lib
静态库的制作:
gcc 获得 .o 文件
将 .o 文件打包,使用 ar 工具(archive)
ar rcs libxxx.a xxx.o xxx.o
r – 将文件插入备存文件中
c – 建立备存文件
s – 索引
2.1实战制作
1.首先创建需要编为库的代码文件
2.生成这些文件的.o文件
gcc -c add.c div.c mult.c sub.c
3.创建静态库文件
ar rcs libcalc.a add.o sub.o mult.o div.o
libcalc是自己起的静态库名字
2.2静态库使用
准备:根据上面操作创建如下目录
mian.c内容
2.使用 gcc main.c -o test -I ./include/ -l calc -L ./lib/
-I指定头文件地址; -l包含该名字库文件; -L 指定库文件路径
由此生成了可执行文件test
3.动态库的制作和使用
3.1动态库制作
命名规则:
Linux : libxxx.so
lib : 前缀(固定)
xxx : 库的名字,自己起
.so : 后缀(固定) 在Linux下是一个可执行文件
Windows : libxxx.dll
动态库的制作:
gcc 得到 .o 文件,得到和位置无关的代码
gcc -c –fpic/-fPIC a.c b.c
gcc 得到动态库
gcc -shared a.o b.o -o libcalc.so
3.2动态库工作原理
- 静态库:GCC 进行链接时,会把静态库中代码打包到可执行程序中
- 动态库:GCC 进行链接时,动态库的代码不会被打包到可执行程序中
- 程序启动之后,动态库会被动态加载到内存中,通过 ldd (list dynamic dependencies)命令检查动态库依赖关系
- 如何定位共享库文件呢?
当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路 径。此时就需要系统的动态载入器来获取该绝对路径。对于elf格式的可执行程序,是 由ld-linux.so来完成的,它先后搜索elf文件的 DT_RPATH段 ——> 环境变量 LD_LIBRARY_PATH ——> /etc/ld.so.cache文件列表 ——> /lib/,/usr/lib 目录找到库文件后将其载入内存。
3.3制作实战
1.首先准备如下目录文件
2.生成目标源代码对应.o文件
gcc -c -fpic add.c div.c mult.c sub.c -I ../include
制作动态库一定要加上 -fpic 参数
3.生成动态库.so文件
gcc -shared add.o sub.o mult.o div.o -o ../lib/libcalc.so
4.使用.so文件
如下是一个错误示范,仅仅在编译时使用参数-l指定动态库路径是无效的!!!
正确示范:
方法一:导入动态库.so文件路径(这只是临时的,终端关闭重启需要重新配置)
方法二:更改用户目录下的 ~/.bashrc 文件(用户级别)
vim .bashrc 跳到bashrc文件最后一行加入
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/whq/linuxProgram/lession06/library/lib
再使配置起作用: source .bashrc
方法三:更改系统目录下的 vim /etc/profile
步骤如方法二一样
4.静态库与动态库区别
静态库:
优点:1.静态库被打包到应用程序中加载速度快。 2.发布程序无需提供静态库,移植方便
缺点:1.消耗系统资源,浪费内存。 2.更新、部署、发布麻烦
动态库:
优点:1.可以实现进程间资源共享(共享库) 2.更新、部署、发布简单。 3.可以控制何时加载动态库
缺点:1.加载速度比静态库慢。 2.发布程序时需要提供依赖的动态库