C++编译流程

C++ 编译流程

C/C++是编译型高级语言,程序要执行,必须要有编译器和链接器。编译过程分为四步:预处理、编译、汇编、链接。

1.预处理

读取源代码并对其中的以#开头的指令和特殊符号进行处理。具体处理方式如下:
1.#define A B,将源代码中所有的B用A代替(这里只是单纯的替换,不进行语法检查,若是较复杂的代码建议加括号)。
2. #include<…>,导入头文件(一般在/usr/ include目录)
3. #include"…",导入自定义头文件(与C/C++源程序放在同一目录)
4. 处理条件编译指令,如:1.#undef(取消已定义的宏) 2.#if(如果给定条件为真,则编译下面代码) 3.#ifdef (如果宏已经定义,则编译下面代码) 4.#ifndef (如果宏没有定义,则编译下面代码) 5.#elif如果前面的#if给定条件不为真,当前条件为真,则编译下面代码,是else if的简写 6.#endif结束一个#if……#else条件编译块。
5.将那些不必要的代码过滤掉,如注释。
6.保留所有的#pragma 编译器指令并添加行号和文件标识,这样编译时编译器就会产生调试用的行号信息,出现警告或错误时也会显示行号。

gcc -E  test.c -o test.i 
// C语言使用

g++ -E test.cpp -o test.i
// C++使用

源程序:
C++编译流程_第1张图片
预处理后的程序:
C++编译流程_第2张图片
可以看到#include头文件被展开导致代码行数达到737行,条件编译指令消失,只剩下满足条件的输出代码和空行。

2.编译

将预处理完的文件进行词法、语法、语义分析和优化,在确认所有的指令都符合语法规则之后,将test.i翻译成汇编代码test.s。template(函数模板和类模板)在编译阶段完成具现化。inline(内联)在编译阶段将调用函数的代码替换为函数本体,从而减少函数调用的开销(需要注意一般较短且不包含switch、while等复杂结构控制语句的函数会被展开,若内联的代码过长inline关键字会被编译器忽略,不予展开)。

gcc -S test.i -o test.s
// C语言使用

g++ -S test.i -o test.s
//C++使用

可在编译时进行O1、O2、或O3优化(优化级别从低到高)
下面以C语言为例:

gcc -S test.i -O1 -o test.s
gcc -S test.i -O2 -o test.s
gcc -S test.i -O3 -o test.s

3.汇编并生成机器码

将汇编代码test.s转换成二进制机器码test.o。一般认为汇编和机器码是一一对应的。当然也有例外,现代汇编中的伪指令和复杂的分支循环结构不能与机器码一一对应。

gcc -c test.s -o test.o
//C语言使用

g++ -c test.s -o test.o
//C++使用

4.链接并生成可执行文件

链接是将多个目标文件以及所需的库文件(静态库为XXX.a或XXX.lib,动态库为XXX.so或XXX.dll)链接成最终的可执行文件。

gcc test.o -o test.out
g++ test.o -o test.out

5.执行可执行文件

./test.out

6.补充

gcc -S test.c -o test.s 执行预处理和编译,生成汇编代码test.s
gcc -c test.c -o test.o  执行预处理、编译和汇编,生成机器码test.o
gcc test.c  执行预处理、编译、汇编和链接,生成一个可执行程序,名字默认为app.out,可通过-o指定

你可能感兴趣的:(c++,开发语言)