gcc与g++的安装和使用
首先大致介绍一下gcc和g++.
在此之前,你需要先安装gcc与g++,然后才能进行指令操作.
命令如下:
sudo yum install -y gcc-c++
在命令行输入以上指令后,gcc/g++便成功安装了.
gcc是一个专门用来编译链接c语言的编译器. g++(c++).
gcc只能编译c语言,不能编译c++语言.而g++既可以编译C++语言,也可以编译C语言.
在此之前,我们需要了解一些基础的背景知识.
目录
1.gcc/g++的使用
先教一下怎么直接使用gcc和g++编译成可执行文件.
命令格式:
gcc -o [可执行文件] [要被编译的文件]
或
gcc [要被编译的文件] -o [可执行文件].
g++也是一样的格式.
这里你只要记住 -o后面加可执行文件就行了,无论顺序怎样,剩下的就是要被编译的文件.
例:
我们要把test.c编译成test可执行文件,输入以下命令:
gcc -o test test.c
或
gcc test.c -o test
即可生成一个名为test的可执行文件.
以上是使用的方法,此时如果不想深入研究便可以结束了.掌握以上指令即可;如果继续想深入了解是怎么程序是怎样编译成可执行程序的,可以继续向下看.
---------------------------------------------------------------------------------------------------------------------------------
2.gcc如何生成可执行文件的?
一个C/C++程序变成一个可执行文件,需要经过以下4个过程.
1.预处理
在这个阶段,编译器会对程序做出以下行为:
1.去注释 2.宏替换 3.头文件展开 4.条件编译 等
这里需要介绍一下什么是条件编译.
我们创建一个.c文件,写入以下代码:
#include<stdio.h>
2
3 int main()
4 {
5 printf("Hello, world\n");
6
7
8 //条件编译,如果为Debug模式,就输出“Hello, Debu”,否则输出“Hello,Release”
9 #ifdef DEBUG
10 printf("Hello, Debug\n");
11 #else
12 printf("Hello,Release\n");
13 #endif
14 }
编写好之后,我们使用gcc编译这个文件
gcc file.c
默认会生成一个a.out可执行文件,我们运行(./文件名)它,观察输出结果.
可以看到此时输出Release,可知此时编译并不是以Debug模式编译的.
条件编译大概就是这样,主要是区分系统型号以及编译模式等.方便多平台可以运行.
那么我们如何知道预处理之后的结果呢?
使用以下指令:
gcc –E file.c –o file.i
这段指令的作用是:将file.c 预处理完成后的结果 放到 file.i文件中.
所以选项-E的作用是:
-E:从现在开始进行程序的翻译,如果预处理完成,就停下来!
可以看到生成了一个file.i的文件,这个便是file.c预处理之后的文件。
我们看看两者的区别,首先打开file.c文件,然后在命令行输入:vs file.i,比较两者的区别
首先可以看到头文件被展开了,stdio头文件中被展开了之后,有这么些头文件.
可以看到宏M被直接替换,然后条件编译选择了Release.注释也被去掉了.
注释去掉之后依然是c语言.
2.编译
这个阶段的作用是:将C语言编译成汇编语言.
指令如下:
gcc -S file.i -o file.s
它将我们刚才预处理好的C语言文件编译成汇编语言.
-S:从现在开始进行程序的翻译,如果编译完成,就停下来.
可以看到多出来一个file.s文件,我们打开观察一下:
可以看到原本的C语言文件已经转化成了汇编语言,如寄存器,助记符等.
3.汇编
这一步会将汇编语言转化成 可重定向二进制目标文件。
为什么是可重定位,后面链接会说.
指令:
gcc -c file.s -o file.o
-c作用:从现在开始进行程序的翻译,如果汇编完成,就停下来.
可以看到多出来一个.o文件,我们此时打开它:
可以看到已经转化成了二进制文件.
4.链接
此时你只需要告诉gcc你需要形成什么可执行文件即可.
为了方便演示,我把之前形成的可执行文件删除掉,如下:
此时我们正式链接,比如我们想形成一个名字为file的可执行文件:
gcc file.o -o file
此时可以发现多出了file可执行文件,我们./执行它
可以看到已经成功执行了.
但是具体是怎么样链接的呢,链接的过程是怎样的呢?这里涉及到动静态库.
3.动静态库
一般链接方式有两种:
静态链接 --- 利用静态库
动态链接 --- 利用动态库
先来看以下内容:
通过后缀.so可以知道是动态库
通过dynamically linked可以大致知道是动态链接.
这是只是大体让大家看一下形式.
那么话说回来,我们平常自己写过printf函数吗?
那么肯定大部分人说写过,刚才文件里还写了一个输出hello world呢
其实呢,printf这个函数本身我们并没有实现,只是在用这个函数,那么这个函数在哪呢?
我们要想编译一个程序,一定会包含大量的头文件。这些函数的声明和实现也在这些头文件中.
那我们先来看一下头文件.
ls /usr/include
可以看到存在大量的头文件.
那假设我们需要找一下printf函数的声明,它在stdio.h文件中,我们来看一下
vim /usr/include/stdio.h
从这里可以看到它的声明.
可是只有声明,那实现在哪呢?只有声明没有实现那代码可正常执行不了啊.
实际上,在C语言中,这些实现的源代码并不会直接给你呈现,而是以动静态库的形式存储的.
我们输入:
ls /lib64
可以发现里面存储了所有的动静态库.
所以一般链接的时候呢,是从头文件中找函数的声明,从库中找文件的实现.
把我的代码和库中的代码以某种方式关联起来,形成可执行程序(.exe).
以下是在不同环境下,动静态库所对应的后缀.
在Linux下: .so(动态库), .a(静态库)
在Windows下: .dll(动态库 ), .lib(静态库)
以上是对动静态库的简单的理解.
那么什么是动静态链接呢?
先来说动态链接。
在我们写好我们C语言程序之后,有一些库函数比如printf,scanf,strlen等等,这些在被编译之时,编译器会将其替换成库中的这个函数的地址。
这样在执行到这个函数的时候,编译器便可以根据这个地址找到这个库乃至找到这个函数.
这边是动态链接.
那么什么是静态链接呢?
这个与动态链接不同的是:这些程序在编译时,编译器会直接将库中方法的实现,整体拷贝一份到我们的可执行程序中!而不是那个函数的地址了.
但是缺点也很明显:会占用资源,想想好几份相同的代码拷贝到这里,再次运行一定占用大量的资源.当然优点是不会再依赖库。动态链接和它相反.
gcc 和 g++ 是默认动态链接的.
同时也要注意,使用动态链接也必须要有.so动态库文件。 使用静态链接也必须使用.a静态库文件.
Linux下默认是提供动态库文件的,静态库文件需要自己手动下载,如果感情去想去尝试一下,可以使用一下指令安装静态库:
C静态库:
sudo yum install -y glibc-static
C++静态库
sudo yum install -y libstdc++-static
更多推荐
所有评论(0)