第1章 GCC编译器

GCC编译器: GCC(GNU Compiler Collection)是由 GNU 开发的编程语言编译器。 GCC最初代表“GNU C Compiler”,当时只支持C语言。 后来又扩展能够支持更多编程语言,包括 C++、Fortran 和 Java 等。 因此,GCC也被重新定义为“GNU Compiler Collection”,成为历史上最优秀的编译器, 其执行效率与一般的编译器相比平均效率要高 20%~30%。 GCC编译器。 linux系统天生带有gcc编译器。

MinGW MinGW是用于windows系统的编译器。

GCC编译工具链

GCC编译工具链(toolchain),是指以GCC编译器为核心的一整套工具。它主要包含以下三部分内容:

gcc-core:即GCC编译器,用于完成预处理和编译过程,把C代码转换成汇编代码。 Binutils :除GCC编译器外的一系列小工具包括了链接器ld,汇编器as、目标文件格式查看器readelf等。 glibc:包含了主要的 C语言标准函数库,C语言中常常使用的打印函数printf、malloc函数就在glibc 库中。 在很多场合下会直接用GCC编译器来指代整套GCC编译工具链。

g++编译器是用来编译cpp文件的。

编译的4个阶段

GCC 编译工具链在编译一个C源文件时需要经过以下 4 步:

预处理:为把头文件的代码、宏之类的内容转换成生成的.i文件,还是C代码。 编译:把预处理后的.i文件通过编译成.s文件,汇编语言。 汇编:将汇编语言文件生成目标文件.o文件,机器码。 链接:将每个源文件对应的.o文件链接起来,就生成一个可执行程序文件。

预处理阶段

新建一个简单的test.cpp文件

#include<iostream>
using namespace std;

int main()
{
    cout<<"This is my first test file!"
    return 0;
}

执行预编译命令:

  • 预处理,可理解为把头文件的代码汇总成C代码,把*.c转换得到.i文件。
  • -E 选项指示编译器只对输入文件进行预处理
g++ -E test.cpp -o test.i

生成test.i文件,使用vim打开如下

编译阶段

  • -S 编译选项告诉g++在为c++代码产生了汇编语言文件后停止编译,会产生一个.s文件(汇编文件)
g++ -S test.i -o test.s

产生的文件内容如下:

汇编阶段

  • -c 选项告诉g++把源代码编译为机器语言的目标代码
  • 产生一个.o文件(目标文件)
g++ -c test.s -o test.o

链接阶段

  • -o 选项指定了产生的可执行文件的文件名
g++ test.o -o test

执行./test命令:输出如下

This is my first test file!

在这里直接执行test命令的话,什么也不会发生,报错也不会!那么test的意义究竟是什么?

test

直接生成可执行文件

执行编译命令:会直接生成可执行文件test

g++ test.cpp -o test

执行./test命令——输出如下

This is my first test file!

综上可以发现:g++ test.cpp -o test 会直接生成可执行文件,而且不会产生中间文件。 这里做个实验:我们先移除其它文件,保留.cpp文件,直接使用g++不加参数生成test.i文件

g++ test.cpp -o test.i

然后执行./test.i文件会发现依旧会输出如下内容

This is my first test file!

所以我们可以发现,不加参数的情况下,不管-o后面的文件是什么后缀,产生的都是可执行文件。 再做一个实验:我们先移除其它文件,只保留.cpp文件,先生成.i文件,然后再执行g++命令。

g++ -E test.cpp -o test.i
g++ test.i -o test

我们会发现,在不加参数限制的情况下,g++命令都会直接生成可执行文件。

g++重要编译参数

-g参数

  • -g 编译带调试信息的可执行文件
g++ -g test.cpp -o test

-O选项

  • -O[n]表示优化等级:一般我们选择-O2
g++ -O2 test.cpp -o test

-l与-L指定库文件|库文件路径

  • -l参数就是用来指定程序要链接的库,-l参数紧接着的就是库名。
  • 在/lib和/usr/lib和/usr/local/lib里的库直接使用-l参数就能链接
//链接glog库
g++ -lglog test.cpp
  • 如果库文件没有放在上面三个目录里,则需要使用-L参数来指定库文件所在目录
  • -L参数后跟着的就是库文件的目录名
  • 指定库文件目录后,需要再用-l参数指定库文件
g++ -L/home/omm/mytestlibfolder -lmytest test.cpp

-I指定头文件搜索目录

  • /usr/include目录一般是不用指定的,gcc知道去那里找。但是如果头文件不在/usr/include里我们就要用-I参数来指定了。-I的是顺序可以任意放置,-I与头文件目录之间可以加空格或者不加空格。
g++ -I./myInclude test.cpp

-Wall 打印警告信息

  • -Wall 打印警告信息
  • 默认生成可执行的a.out文件
g++ -Wall test.cpp

-w 关闭警告信息

  • -w 关闭警告信息
g++ -test.cpp

-std=c++11 设置编译标准

  • -std=c++11 设置编译标准

-o 指定输出的文件名

  • 如果不加上该参数就会默认生成a.out文件
g++ test.cpp -o test

-D 定义宏

在使用gcc/g++的时候定义宏。

第2章 GCC实战

新建swap.cpp文件

新建src文件夹,在该文件夹下存放swap.cpp文件

void swap(int& a,int& b)
{
	int temp=a;
	a=b;
	b=temp;
}

新建swap.h文件

新建myInlucde文件夹,在该文件夹下存放swap.h文件

void swap(int& a,int& b);

新建main.cpp文件

#include<iostream>
#include"swap.h"
using namespace std;
int main()
{
	int a=111;
  	int b=222;
	cout<<"a="<<a<<" "<<"b="<<b<<endl;
	cout<<"交换a和b"<<endl;
	swap(a,b);
	cout<<"a="<<a<<" "<<"b="<<b<<endl;
	return 0;
}

执行编译

编译

g++ main.cpp ./src/swap.cpp -I myInlcude -o main

编译过后产生可执行文件main,执行该文件

./main

怎样通过设置环境变量的方式在其它目录下执行main程序呢?