一文看懂C/C++编译过程以及g++编译选项

文章介绍了Linux系统中使用gcc/g++编译C++程序的过程,包括预处理、编译、汇编和链接四个阶段,并详细列举了如何通过-E、-S、-c等编译选项控制这些阶段,生成预处理文件、汇编文件和目标文件。此外,还讨论了直接从源文件生成可执行文件的情况以及编译选项如-o、-I、-L、-l等的用途。
摘要由CSDN通过智能技术生成

前言

在linux系统下,输入man g++,即可以看到gcc官方文档对gcc编译选项的详细说明,本文也主要是在官方文档基础上,对gcc/g++编译过程和一些编译选项进行了总结和说明,希望对学习这块内容的人有所帮助。

1、编译的四个阶段

一般我们使用gcc/g++将源码编译为可执行文件,编译过程仔细划分的话,可以分为4个阶段:预处理、编译、汇编、链接。以add.cpp为源文件进行举例说明。

  • 预处理

这一步主要是替换掉源文件中定义的宏,比如替换#include包含的头文件,替换define定义的宏变量等。预处理之后的文件形式上还是源码,只是对源码有些地方做了替换。预处理后的文件名后缀为.ii 。

  • 编译

将预处理的之后的源码编译为汇编代码。汇编后缀为.s

  • 汇编

将汇编代码汇编生成目标文件。目标文件后缀为.o

  • 链接

将一个或几个目标文件链接在一起,形成一个可执行文件。

2、通过编译选项来控制编译过程

还是以add.cpp为例,如果要生成各个阶段的文件,可以通过编译选项来控制。

  • 生成预处理.ii文件

编译选项为 -E,这里一定要用-o 指定输出的文件名,不然默认是输出到屏幕。其它几个阶段可以不用指定输出文件名。

g++ add.cpp -E -o add.ii  #需要指定输出文件名,得到add.ii
  • 生成汇编.s文件

编译选项为-S,可以不用-o指定输文件名,默认为add.s,当然也可以指定。

g++ add.ii -S        # 默认输出文件名为add.s
# 也可以直接一步从源文件得到.s文件
g++ add.cpp -S  
  • 生成目标.o文件

编译选项为-c,可以不用-o指定输出文件名,默认为add.o。

g++ add.s -c       # 从汇编文件得到目标文件
# 也可以从源文件或与预处理后文件得到目标文件
g++ add.ii -c      # 从预处理之后的文件得到目标文件
  • 生成可执行文件

一般每个.cpp文件经过处理之后,都能得到一个目标.o文件,可以将多个目标文件链接成一个可执行文件。假如main.cpp,也生成了main.o文件,那么将main.o和add.o链接成一个可执行文件。

不需要编译选项,可以用-o指定可执行文件的文件名,如果不指定默认为a.out

g++ main.o add.o    # 默认生成a.out
g++ main.o add.o  -o main # 指定可以执行文件名为main

值得说明的是,编译选项只是指定编译过程的结束阶段,并未要求输入文件阶段,因此跳过中间某一个过程也是可以,比如从.cpp文件直接生成可以执行文件。涉及多个文件时,不同文件处于不同阶段也是可以的。比如一个为源文件,一个为汇编文件,然后用这个两个文件生成可执行性文件也是ok的:

g++ main.cpp add.s -o main

3、一个编译案例

假如main.cpp、add.cpp和add.h位于同一个目录下面,每个文件的具体内容如下:

// main.cpp
#include <iostream>
#include "add.h"
using namespace std;
int main ()
{
    cout << "add result is:" << add(500, 20) << endl;
    return 0;
}
// add.h
int add(int num1, int num2);
// add.cpp
#include "add.h"
int add(int num1, int num2) {
    return num1 + num2;
}

linux系统下,进入到三个文件所在目录,依次执行下面3个命令:

g++ add.cpp -E -o add.ii  # 生成add.ii
g++ add.ii -S             # 生成add.s
g++ add.s -c              # 生成add.o

会依次生成add.ii 、add.s、 add.o三个文件。此时目录文件情况为:

add.cpp add.h add.ii add.o add.s main.cpp

然后使用下面的命令,直接将main.cpp和add.o生成可以执行文件,相当与省略了main.cpp编译的中间过程。

g++ main.cpp add.o -o main

此时目录情况为:

add.cpp add.h add.ii add.o add.s main main.cpp

然后输入 ./main 可以看到打印如下,说明编译过程正确。

# add result is:520

4、g++编译选项总结

前面提到可以编译选项-E、-S、-c来指定编译的终止阶段,如果不加编译选项,默认生成可以执行文件。其它常用的编译选项有:

-o filename 指定输出文件名

-I dir,(大写i,可理解为include首字母),将dir添加到头文件的查找路径,即如果头文件在dir可以确保查找头文件成功。

-llibrary 或 -l library(不推荐),如果需要连接库library,指定链接库library。

-L dir,为-l中指定的库添加搜索目录dir,即如果library在dir可以确定搜索到

-shared以及-fpic或-fPIC,生成动态库时需要,pic表示postion independent code,即生成与位置无关的代码。

-std=standard,执行标准,如-std=c++11。

-g,编译时产生调试信息,比如要使用gdb进行调试,就要加上该选项。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值