目录
GCC
gcc简介:
gcc(GNU Compiler Collection,GNU编译器套件)是由 gnu 开发的编程语言 译器。gnu 编译器套件包括C、C++、Objective-C、Java、Ada 和 Go 语言前端,也包括了这些语言的库(如 libstdc++,libgcj等)。
gcc 不仅支持 C 的许多“方言”,也可以区别不同的 C 语言标准;可以使用命令行 选项来控制编译器在翻译源代码时应该遵循哪个 C.
gcc/g++的区别:
注:gcc编译器只能用来编译c语言,g++可以编译c语言也可以编译c++。在一些具体的语法规则上,C++在编译过程中的语法检查会更加严格。C++语言本身在编译 过程中也会引入C++的标准库,如果使用gcc编译器直接编译C++语言会在编译过程中添加额外的参数,这样会显得编译过程较为繁琐。为了更方便使用编译器,我们选择g++来编译C++代码。
gcc的完成:
对于gcc而言,具体的过程:【预处理】--->【编译】--->【汇编】--->【连接】
预处理(进行宏替换):
预处理功能主要包括 头文件展开,宏替换,去注释,条件编译 等。
gcc –E file.c –o file.i
“-E” 的作用是让 gcc 在预处理结束后停止编译过程。
“ -o ” 是指目标文件,“-o”后面紧跟的是后面你所形成的文件的名称" .c "文件是源文件,“ .i ”文件是 已经过预处理的 C 原始程序
编译(生成汇编):
在这个阶段中 ,gcc 首先要检查代码的规范性、是否有语法错误等 , 以确定代码的实际要做的工作 , 在检查无误后,gcc 把代码翻译成汇编语言。
gcc –S file.i –o file.s
“-S” 只进行编译而不进行汇编,从而生成汇编代码。
“.i”
结尾的文件表示源程序;“.s”
结尾的文件表示经过编译生成的汇编代码
汇编(生成机器可识别代码):
汇编阶段是把编译阶段生成的 “.s” 文件转成目标文件
gcc –c file.s –o file.o
“ -c ” 就可看到汇编代码已转化为 “.o” 的二进制目标代码
“.s”
结尾的文件表示经过编译生成的汇编代码;“.o”
结尾的文件表示经过编译生成的汇编代码
连接(生成可执行文件或库文件):
在成功编译之后 , 就进入了链接阶段。
gcc file.o –o file
将可重定位目标二进制文件,和库进行链接形成可执行程序
在这里涉及到一个重要的概念:函数库
我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?最后的答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定时,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函 数“printf”了,而这也就是链接的作用。
技巧:gcc命令选项与生成文件后缀:
命令选项:
-E
-S
-c
【键盘左上角的Esc,只有c是小写】
文件后缀:.i
.s
.o
【.iso为镜像文件的后缀,ISO也为国际标准化组织】
动态库,静态库 :
动态库,静态库简介:
静态库是指编译链接时 , 把库文件的代码全部加入到可执行文件中 , 因此生成的文件比较大 , 但在运行时也就不再需要库文件了。其后缀名一般为“.a”动态库与之相反 , 在编译链接时并没有把库文件的代码加入到可执行文件中 , 而是在程序执行时由运行时 链接文件加载库, 这样可以节省系统的开销。动态库一般后缀名为 “.so”, 如前面所述的 libc.so.6 就是动态 库。gcc 在编译时默认使用动态库。完成了链接之后 ,gcc 就可以生成可执行文件。
动态库,静态库的格式:
库的本质:就是一个文件
动态库:
liunx下以lib为前缀,.so为后缀
格式:【 libfilename.soXXXX】
window:以dll结尾
静态库:
liunx下:.a为后缀
window:.lib后缀
注:在我们的机器上,默认只会安装 动态库,静态库是没有安装的。
查询c的动态库静态库:
cd /lib64/
ls
ls /lib64/libc*
ls /lib64/libc.so*
ls /lib64/libc.a*
【ldd】指令:
ldd filename —— 检测可执行程序形成的时候都依赖了哪些库
l -> list 【列出】
d -> dynamic 【动态的】
d -> dependencies【依赖关系】
- 然后我们就可以去看看每次gcc最终链接后形成的
text
这个可执行程序都依赖了哪些库。然后可以看到起来的这个就是标准的C语言库
感性理解动态库,静态库:
高中星期学校就放半天假,张三想出去玩,从李四(混混)那里得知校外有个网吧,就去校外的网吧打游戏。张三在网吧玩了半天玩爽了就回宿舍,舍友们知道张三去了网吧玩,不带他们气愤了,舍友几个就打算也去网吧玩。他们刚去,碰到警察查身份证,结果是黑店,查封了,舍友们就只能回宿舍呆着了。
上图里(人物对应):
李四:编译器
网吧:动态库 (只有一个)
张三和舍友们:可执行的程序
这里的动态库不能缺失,一旦缺失,影响的不止一个程序,可能很多程序都无法正常运行。
张三看舍友回来,得知网吧查封,李四也知道了,李四就去二手手机店淘手机,开个手机店,按小时收费借给张三和舍友们玩。但李四这是非法经营,结果查封了,张三和舍友并不知情。
手机:静态库
张三和舍友们:可执行的程序
李四:编译器
在编译器使用静态库进行静态链接的时候,会将自己的方法拷贝到目标程序,该程序以后就不需要再依赖静态库!
验证:
使用上述的ldd指令
要想使用静态库需要输入:
gcc a.c -o test-static -static
相当于再结尾加了一个 -static
静态库的安装:
c静态库:
root用户:yum -y glibc-static
普通用户:sudo yum -y glibc-static
c++静态库:
root用户: yum -y install libstdc++-static
普通用户:sudo yum -y install libstdc++-static
对于动态链接和静态链接所产生的可执行文件大小不太一样 ,差了可是100多倍!
所以这就是为什么云服务器默认就是以动态链接进行编译了,因为静态链接虽然是无需调用库函数,但是形成的程序体积会非常庞大;而且其中有一部分库的代码,然后系统中本身又带有库,这就造成了磁盘空间的浪费。
动态库,静态库的优缺点:
【动态链接】 —— 仅仅是把库中的你所用的方法的地址拷贝到程序里 。
动态库优点:因为可以做到被大家共享方法,所以真正的实现永远都是在库中,程序内部只有地址,比较节省空间。
动态库缺点:我们的程序还是依赖任何库,一旦动态库缺失,我们的程序便无法运行。
【静态链接】 —— 自己代码当中用到的库中的方法直接拷贝到程序里 。
静态库优点:我们的程序不依赖任何库,自己就可以独立运行。
静态库缺点:因为自身的拷贝问题比较浪费空间。
以上是对gcc/g++,动态库,静态库的简单理解。 以后有更深的理解,会再续更新。