在自学Linux相关的知识,学习了GCC、GDB、Makefile等xian相关知识,本想将zhe'这段时间所学东西zong总结一下,奈何肚子里墨水严重不足,盯着屏幕半个小时愣是写不出东西。首先时自己确实学艺不精写不出太深的东西,其次自己写作写作水平有限,写不好什么。就将记的笔记总结一下,再在网上一些内容添加进去丰富一下。
相关博客http://blog.csdn.net/eastonwoo/article/details/8655243
相关博客http://blog.sina.com.cn/s/blog_5ff8e88e01015tga.html
相关博客https://blog.csdn.net/qq_31108501/article/details/51841983
相关博客https://www.cnblogs.com/king-lps/p/7757919.html
一、GCC简介
GCC即GNU C Compiler,时GNUtui'推出的功能qian强大、性能优越的多平台编辑器,是GNU的GCC编代表作之一。GCC可以在多种硬件平台上编译出可执行程序,其执行效率与一般的编译器相比平均效率要高20%~30%。GCC编译器能将C、C++语言源程序、汇编程序编译/连接成可执行文件。在Linux系统中,可执行文件没有统一的后缀,系统从文件的属性来区分可执行文件和不可执行文件。文件的属性fe分为可读、可写、可执行三种。其查看方式为,在命令行中敲击 ls -l,
如图,ls命令为显示当前目录中的文件,加-l即显示当前目录中文件的具体信息,如读写权限、文件所有者、修改日期等。
图中文件最前面显示的即读写权限,分为三部分,r:可读、w:可写、可执行。上图中hello文件有可执行权限,即可执行文件。
GCC编译一般使用指令 gcc hello.c -o hello 可将hello.c编译成名为hello的可执行文件.
二、编译过程
程序在编译时,GCC需要调用预处理程序cpp,由它负责展开在源文件中定义的宏,并向其中插入“#include”语句所包含的内容。接着GCC会调用ccl和as将处理后的源代码编译成目标代码。最后GCC会调用链接程序ld把生成的目标代码链接成一个可执行程序。
也就是说使用GCC编译程序时,编译过程可细分为四个阶段:预处理阶段、编译、汇编、链接。
预处理阶段(Pre-Processing)
使用-E参数可以让GCC在预处理结束后停止编译过程
#gcc -E hello.c -o hello.i
此时若查看hello.i文件中的内容会发现stdio.h的内容却是插到文件中去了,而其他相应被预处理的宏定义也都做了相应的处理。
在hello.i文件中最后仍可看到那熟悉的面孔,hello.c中main函数部分的程序仍然在里面,只是将“stdio.h”的内容插入到hello.i中。如果感兴趣可在 /usr/include 目录中找到“stdio.h”的头文件。
编译(Compiling)
接下来时代码的编译阶段,在这个阶段中GCC首先要jia检查代码的规范性、是否由语法错误等,以确定代码的实际要作的工作。在检查无误后GCC把代码翻译成汇编语言。用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。汇编语言是非常有用的,它为不同高级语言不同编译器提供了通用的语言。
使用指令gcc -S hello.i -o hello.s执行编译过程。打开生成的hello.s文件如下图所示
图中即为hello.s文档的内容。
汇编阶段(Assembling)
汇编阶段是把编译阶段生成的“hello.s”文件转成目标文件,可使用”-c“参数可看到汇编代码转化为".o"的二进制代码。
输入gcc -c hello.s -o hello.o指令生成hello.o文件,打开如图所示
显示的为乱码,实则是已经转换的二进制代码。
链接(Lking)
成功编译之后,就进入了链接阶段。在这个阶段涉及一个重要概念:库函数。
库函数这部分还未理解透,没敢太造次,这部分先跳过。在链接过程中系统将库函数li
链接生成可执行文件。
使用gcc hello.o -o hello指令生成可执行文件hello。运行该文件得出正确结果。
三、GCC使用
1、文件类型
GCC通过后缀来区别输入文件的类别:
.c为后缀的文件:C语言源代码文件
.a为后缀的文件:是由目标文件构成的库文件
.C、.cc或.cxx为后缀的文件:C++源代码文件
.h为后缀的文件:头文件
.i为后缀的文件:已经预处理过的C源代码文件
.ii为后缀的文件:已经预处理的C++源代码文件
.o为后缀的文件:编译后的目标文件
.s为后缀的文件:汇编语言源代码文件
.S为后缀的文件:经过预编译的汇编语言源代码文件
2、编译选项
GCC最基本的用法是:
gcc [options] [filenames]
options:编译器所需要的编译选项。
filenames:要编译的文件名。
关于编译选项,GCC编译器的编译选项大约有100多个,其中多数选项基本用不到,这里只介绍其中最基本、最常用的参数。
-o output_filename:确定可执行文件的名称为output_filename。如果不给出这个选项,gcc就给出预设的可执行文件a.out。
-c:只编译,不链接成可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件。
-g:产生调试工具(GNU的gdb)所必要的符号信息,如果需要对编译的程序进行调试就必须加上这个选项。
-O:对程序进行优化编译、链接,采用这个选项,整个源代码会在编译、链接过程中进行优化处理。这样产生的可执行文件的执行效率可以提高,但编译、链接的速度就相应的要慢一些。
-O2:比-O更好的优化编译、链接,当然整个编译、链接过程会非常慢。
-l dirname:将dirname所指出的目录加入到程序头文件目录列表中。
如程中:
#include<stdio.h>
#include "a.h"
对于<>,预处理程序cpp在系统预设的头文件目录(/usr/include)中搜索相应的头文件,er
而对于”“,cpp在当前目录中搜索头文件,这个选项是告诉cpp,如果当前目录中没找到需要的头文件,就到指定的dirname目录中寻找。
例:gcc main.c -l /home/include -o main
是先到预设路径中寻找,然后再到/home/include目录下搜索头文件。
-Ldirname:将dirdirname所指出的目录加入到库文件的目录列表中。在默认状态下,连接程序ld在系统的预设路径中(/usr/lib)寻找所需要的库文件,这个选项告诉连接程序,首先到-L指定的目录中去寻找,然后再到系统预设的路径中寻找。
-lname(小写的L):再连接时,装载名字为"libname.a"的函数库,该函数库位于系统预设的目录或者由-L选项确定的目录下。
例:gcc main.c -L /home/lib -lmain -o main
-static:静态链接库文件
例:gcc -static hello.c -o hello
-Wall:生成所有警告信息
-w:不生成任何警告信息
-DMACRO:定义MACRO宏,等效于再程序中使用#define MACRO
注:关于-O和-O2参数的编译指令可用一段程序实际测试一下。
首先使用普通的编译指令编译:
在使用time ./main指令运行,time指令可记录程序运行时间。实际测试可得,上述程序执行时间为7.561s。如下图:
删除main可执行文件后在使用-O指令编译:
再次用time ./main指令运行main,得出时间为5.959s:
再将main文件产出,使用-O2指令编辑:
再次用time ./main指令运行main,得出执行时间为5.990s: