今天主机频道就和大家分享一下在linux中如何使用gcc的相关知识点。内容详实,逻辑清晰。我相信大部分人都太了解这些知识了,所以我把这篇文章分享给大家,供大家参考。希望你看完这篇文章有所收获。让我们一起来看看吧。
在linux中,gcc的全称是“GNU编译器集合”,中文意思是“GNU编译器套件”。GCC是GNU开发的编程语言编译器,可以编译多种语言。Gcc套件包括C、C++、Objective-C、Fortran、Java、Ada和Go语言的前端,以及这些语言的库。
1.什么是gcc?
GCC(GNU Compiler Collection,GNU compiler suite)是GNU开发的编程语言编译器,可以编译多种语言。GNU编译器套件包括C、C++、Objective-C、Fortran、Java、Ada和Go,以及这些语言的库(如libstdc++、libgcj等。)
起初,gcc被用作C语言的编译器(GNU C编译器)。现在除了C语言,还支持C++、java、Pascal等语言。Gcc支持多种硬件平台。
2.gcc的特点
Gcc是一个可移植的编译器,它支持多种硬件平台。如ARM、X86等。
Gcc不仅是本地编译器,还可以跨平台交叉编译。所谓本地编译器,就是编译后的程序只能在本地环境下运行。gcc编译的程序可以在其他平台上运行。比如嵌入式程序可以在x86上编译,然后在arm上运行。
Gcc有一个用于解析不同语言的多语言前端。
Gcc是以模块化的方式设计的,可以被新的语言和新的CPU架构所支持。
Gcc是自由软件。任何人都可以使用或更改这个软件。
3、gcc编译过程
Gcc编译器主要经历四个过程:
预处理
收集
装配(装配)
链接(链接)
预处理其实就是扩展头文件和宏。在编译阶段,gcc调用不同语言的编译器,比如C语言的ccl。Gcc实际上是一个工具链,在编译程序的过程中调用不同的工具。在组装阶段,gcc调用组装器进行组装。链接过程会将程序需要的目标文件链接成可执行文件。汇编程序生成一个可重定位的目标文件。学习了操作系统后,我们知道源程序中的地址是从0开始的,这是一个相对地址,而程序在内存中实际运行时的地址肯定不是从0开始的,写源代码时无法知道程序的绝对地址,所以重定位可以将源代码的代码和变量定位为具体的内存地址。
我们来拍张图展示一下这个过程。注意过程中文件的后缀变化,编译选项与这些后缀有关。
以上是GCC编制的四个步骤。
4.gcc常见选项
让我们来看看gcc常见的选项。
现在我们有了源文件hello.c下面是一些使用gcc的例子:
Gcc -E hello.c -o hello.i预处理hello.c文件并生成hello.i文件。
Gcc -S hello.i -o hello.s编译预处理文件并生成汇编文件。
Gcc -c hello.s -o hello.o编译汇编文件并生成目标文件。
Gcc hello.o -o hello链接目标文件生成可执行文件。
Gchello.c-ohhello直接编译链接成一个可执行的目标文件。
编译gcc-hello.c或gcc -c hello.c -o hello.o以生成可重定位的目标文件。使用gcc时,可以添加-Wall选项。在本例中,如果没有添加-Wall选项,编译器将不会报告任何错误或警告,但程序的结果不是预期的:
//bad.c
# include & ltstdio.h & gt
int main()
{
printf(& quot;号码是% f & quot,5);//程序输出的数字是0.000000,结果是错误的。
返回0;
}使用-Wall选项:
Gcc -Wall bad.c -o badgcc将输出一条警告消息:
警告:格式“%f”需要类型为“double”的参数,但参数2的类型为“int”[-w format =]
printf(& quot;号码是% f \ n & quot,5);5.gcc编译多个文件。
// hello.c
# include & ltstdio.h & gt
#包含& quot你好。& quot
void printHello()
{
printf(& quot;你好世界!\ n & quot);
}//main.c
# include & ltstdio.h & gt
#包含& quot你好。& quot
int main()
{
print hello();
返回0;
}//hello.h
//只包含函数声明。
#ifndef _HELLO_
#define _HELLO_
void print hello();
#endif编译这三个文件,可以一次编译:
gcc hello.c main.c -o main生成的可执行文件main也可以独立编译:
gcc -Wall -c main
gcc -Wall -c hello.c -o hello.o
gcc -Wall main.o hello.o -o main独立编译的好处是,当其中一个模块发送变更时,只需编译该模块,无需重新编译所有文件,可以节省编译时间。
6.使用外部库
用C语言和其他语言编程时,我们需要头文件来提供常量的定义和系统、库函数调用的声明。库文件是根据可重用性原则编写的预编译函数的集合。它们通常由一组相互关联的可重用原则编写,并且通常由一组用于完成共同任务的相互关联的功能组成。使用库的优点是:
模块化开发
复用性
可维护性
库可以分为静态库和动态库:
静态库(。a):程序在编译链接时将库的代码链接到可执行文件。程序运行时不再需要静态库。静态库占用更多的磁盘空间,程序不能共享静态库。运行时也是相对内存密集型的,因为每个程序都包含一个静态库。
动态库(。所以还是。sa):共享库的代码只在程序运行时链接,多个程序共享使用该库的代码,从而减少程序的大小。
通用头文件或库文件的位置是:
包含/usr/include下的文件夹及其子目录。
/usr/local/include及其子目录下的include文件夹。
/usr/lib
/usr/local/lib
/库
7.生成静态库
为了生成。一个文件,我们需要生成。o档。以下命令行将我们的hello.o打包到静态库libhello.a中:
Arrcs libhello.ahelo.oar是一个枪械存档工具,rcs代表replace和create。如果以前存在libhello,将创建并替换一个新的libhello.a。
然后就可以像这样使用静态库libhello.a了。
还有另一种使用gcc -Wall main.c libhello.a -o main的方法:
gcc-wall-L . main . c-o main-Lhello[Lhello是libhello的缩写]其中-l表示库文件的位置在当前目录中。由于libhello.a是我们自己生成的,存储在当前记录中,所以需要添加-l选项。默认的库文件是在系统目录中搜索。类似地,-i .选项用于搜索头文件。
8.生成共享库
生成一个名为libxxx.so的共享库,刚才从hello.o生成libhello.so的命令是:
gcc-shared-fpichello . o-o lib hello . so生成共享库后,可以如下使用共享库:
Gcc -Wall main.o -o main -L. -lhello该命令与使用静态库的命令相同,但在共享库和静态库共存的情况下,共享库优先。
有时共享库不在当前目录中。为了让gcc找到共享库,有几种方法:
复制。所以文件到系统共享库的路径,一般指/usr/lib。
在~/。bash_profile文件,配置LD_LIBRARY_PATH变量。
配置/etc/ld.so.conf,配置完成后调用ldconfig更新ld.so.cache。
其中共享选项表示生成共享库格式。FPIC的意思是生成一个与位置无关的代码,这意味着它的操作和加载与内存位置无关,可以在任何内存地址加载。
9.库的搜索路径
库的搜索路径遵循几个搜索原则:从左到右搜索-I -l指定的目录,如果在这些目录中找不到,gcc将从环境变量指定的目录开始搜索。头文件的环境变量是C_INCLUDE_PATH,库的环境变量是LIBRARY_PATH。如果仍然找不到,将从系统指定的目录中进行搜索。
评论前必须登录!
注册