此系列文章的目的:1.希望能够掌握之前理解不清楚和根本没有掌握的知识点
2 也算是一次复习,拓实基础,为笔试面试做准备吧
GCC 编译分为4个部分,预处理,编译,汇编,链接
假设源文件:test.c
预处理:
命令如下:
gcc -E test.c -o test.i
参数-E表示只进行预处理,预处理器的活动:
1.将所有的#define删除,并且展开所有的宏定义
2.处理所有的条件预编译指令,比如#if #ifdef #elif #else #endif等
3 处理#include 预编译指令,将被包含的文件插入到该预编译指令的位置。
4 删除所有注释 “//”和”/* */”.
5 添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号。
6 保留所有的#pragma编译器指令,因为编译器需要使用它们
1.将所有的#define删除,并且展开所有的宏定义
2.处理所有的条件预编译指令,比如#if #ifdef #elif #else #endif等
3 处理#include 预编译指令,将被包含的文件插入到该预编译指令的位置。
4 删除所有注释 “//”和”/* */”.
5 添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号。
6 保留所有的#pragma编译器指令,因为编译器需要使用它们
示例:
#include<stdio.h>
#include<math.h>
#define YES 1
#ifdef YES
printf("Yes, come here");
#else
printf("Yes haven't been defined!");
#endif
int main()
{
printf( "hello,world\n" );
int x,y;/*x and y need to be assigned*/
if(YES)
printf("%d, %d\n",x,y);
return 0;
}
结果部分代码,前面是stdio.h头文件内容:
extern int matherr (struct exception *__exc);
# 483 "/usr/include/math.h" 3 4
# 3 "relearn.c" 2
printf("Yes, come here");
int main()
{
printf( "hello,world\n" );
int x,y;
if(1)
printf("%d, %d\n",x,y);
return 0;
}
我们可以发现,之前的工作确实被完成了
编译:
命令:gcc -S test.i -o test.s
编译就是将源代码生成汇编代码,编译过程分为6步,词法分析,语法分析,语义分析,源代码优化,代码生成,目标代码优化
编译原理中的知识:词法分析:就是将源代码的字符序列生成一个个词素或者记号(token)
记号的形式<记号名,属性值(指向符号表中的条目)>,lex工具可实现词法扫描
语法分析:根据第一步的词法单元生成语法分析树,yacc工具可实现语法分析
语义分析:使用语法树和符号表中信息检查源程序和语言定义的语义是否一致
源代码优化:即中间代码生成,将整个语法树转化为中间代码,中间代码和目标机器与运行环境无关的,
中间代码将编译器
分为前端和后端,前端负责产生与机器无关的中间代码,后端负责
将中
间代码转换为目标机器代码
目标代码生成与目标代码优化很容易理解
汇编:
命令: gcc –c hello.c –o hello.o
汇编器将汇编代码生成汇编码,每个汇编语句几乎都对应一个机器指令,翻译过程类似查表