C# · 12月 20, 2021

C语言编译过程

编译过程

总览图

预处理

在此阶段过程中,编译器会根据我们写好的代码,以此分析其中的语句,并对当中的某些语句执行替换,该替换是直接作用于.c文件。

分别处理:注释、#define、条件编译指令、#include。

#include

#define MAXLENGTH 20

int main()

{

int i = 0;

int j = MAXLENGTH;

#ifndef GOOGLE_VERSION

i +=j;

#endif

printf(“%d”,i);//未定义GOOGLE_VERSION 输出20

return 0;

}

在VS下点击“生成解决方案”会执行编译操作,编译第一步执行的便是预处理,生成预处理文件(VS下需进行些许设置才可看见)

相应设置:资源管理器下右击工程->选择属性->点击C/C++->选中预处理器->更选“预处理到文件”属性为是->点击应用再确定。

文件路径:再次点击生成解决方案->右键工程->选中“在文件资源管理器中打开文件夹(X)”->Debug目录下找到.i后缀的文件->.i后缀的文件便是通过了预处理之后的文件(该文件的代码量为膨胀为.c文件的好几倍)。

编译

编译过程按顺序分两步:语句分析和代码优化。

语句分析:

对整体代码进行扫描处理,解析代码的词法、语法、语义,以此排除不合法的、不规范的代码。

词法解析:关键字的正确性、标识符的有效性、立即数的展开。

语法分析:变量命名规范、程序结构合法性、函数定义的正确性、重定义现象等。

语义分析:表达式的合理性、变量的未初始化使用等。

如若以上情况存在不合法性,编译器会停止编译并抛出错误同时显示该错误。

代码优化:

语句分析通过了之后,编译器会针对现有代码最后生成的汇编语句来进行优化处理。存在两种模式的代码优化方式:Debug和Release。

Debug:调试版本,生成便于调试的汇编指令;会根据现有的每一句代码生成对应的汇编语句,存在将现有的一句语句代码细化为几句汇编语句。旨在方便开发者逐句调试代码。

如下为以上程序的Debug版本下的反汇编代码:

#include

#define MAXLENGTH 20

int main()

{

01061790 push ebp

01061791 mov ebp,esp

01061793 sub esp,0D8h

01061799 push ebx

0106179A push esi

0106179B push edi

0106179C lea edi,[ebp-0D8h]

010617A2 mov ecx,36h

010617A7 mov eax,0CCCCCCCCh

010617AC rep stos dword ptr es:[edi]

int i = 0;

010617AE mov dword ptr [i],0

int j = MAXLENGTH;

010617B5 mov dword ptr [j],14h

#ifndef GOOGLE_VERSION

i += j;

010617BC mov eax,dword ptr [i]

010617BF add eax,dword ptr [j]

010617C2 mov dword ptr [i],eax

#endif

printf(“%d”,i);//未定义GOOGLE_VERSION 输出20

010617C5 mov esi,esp

010617C7 mov eax,dword ptr [i]

010617CA push eax

010617CB push 10658A8h

010617D0 call dword ptr ds:[1069114h]

010617D6 add esp,8

010617D9 cmp esi,esp

010617DB call __RTC_CheckEsp (010611D1h)

return 0;

010617E0 xor eax,eax

}

010617E2 pop edi

010617E3 pop esi

010617E4 pop ebx

}

010617E5 add esp,0D8h

010617EB cmp ebp,esp

010617ED call __RTC_CheckEsp (010611D1h)

010617F2 mov esp,ebp

010617F4 pop ebp

010617F5 ret

Relase:发行版本,不会为无效的过程操作(与结果无关)生成汇编指令,旨在降低程序的内存、提高程序的运行速度。

如下为以上程序的Relase版本下的反汇编代码:

int i = 0;

int j = MAXLENGTH;

#ifndef GOOGLE_VERSION

i += j;

#endif

printf(“%d”,i);//未定义GOOGLE_VERSION 输出20

00FB1000 push 14h

00FB1002 push 0FB2100h

00FB1007 call dword ptr ds:[0FB2090h]

00FB100D add esp,8

return 0;

00FB1010 xor eax,eax

}

00FB1012 ret

— f:ddvctoo