<>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++使用
源程序:

预处理后的程序:

可以看到#include<stdio.h>头文件被展开导致代码行数达到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指定

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信