广州木马网站建设公司怎么样,门户网站自查报告,收费图片网站,深圳宝安区有哪些街道目录
前言#xff1a;
前置知识回顾
宏
宏定义常量
宏定义语句
宏定义函数
条件编译
应用场景
编译过程概览
预编译阶段
编译阶段 汇编阶段 链接阶段 前言#xff1a; 在ANSI C的任何一种实现中#xff0c;存在两种不同的环境#xff0c;第1种是翻译环境#x…目录
前言
前置知识回顾
宏
宏定义常量
宏定义语句
宏定义函数
条件编译
应用场景
编译过程概览
预编译阶段
编译阶段 汇编阶段 链接阶段 前言 在ANSI C的任何一种实现中存在两种不同的环境第1种是翻译环境在这个环境中源代码被转换为可执行的机器指令第2种是执行环境它用于实际执行代码将磁盘中的可执行文件装载到内存中CPU才能通过总线读取内存中的指令才能真正执行程序本文重点阐述程序的翻译坏境 前置知识回顾
宏 #define 机制包括了一个规定允许把参数替换到文本中这种实现通常称为宏macro或定义宏define macro 命名习惯 宏名全部大写 //宏的声明:#define name( parament-list ) stuff
//其中的 parament-list 是一个由逗号隔开的符号表它们可能出现在stuff中;
//注意:参数列表的左括号必须和宏名name紧邻;
//如果宏名与参数列表之间有任何空白存在,参数列表就会被解释为stuff的一部分; 宏定义常量 # define ROW 10 //宏定义整型常量
# define PI 3.14 //宏定义浮点型常量
# define STR hello world //宏定义字符串
int main()
{printf(%d %f %s\n, ROW, PI, STR);return 0;
} 运行结果 宏定义语句
# define PRINTF printf(Hello Linux!\n);
int main()
{int i 10;PRINTF;return 0;
}
运行结果 宏定义函数 宏可以接收参数且不用指定参数类型 # define ADD(x,y) ((x)(y))
int main()
{int m 10;int n 10;float d1 4.5;float d2 5.5;printf(%d\n, ADD(m,n));printf(%f\n, ADD(d1, d2));return 0;
}
运行结果 条件编译 编译程序时使用条件编译指令选择性的将一条语句/一组语句编译或者放弃 //常见的条件编译指令
#if 如果条件为真则执行相应的操作;
#elif: 类似于else if的用法当前面条件为假再判断该条件是否为真如果是真则执行相应操作;
#else: 如果前面所有条件均为假则执行相应操作;
#ifdef: 如果该宏已定义则执行相应操作;
#ifndef: 如果该宏没有定义则执行相应操作;
#endif : 结束对应的条件编译指令(不能省略);应用场景 # define VERSION1 1
//# define VERSION2 2
int main()
{
#ifdef VERSION1printf(Hello Version1.0\n);
#elif VERSION2printf(Hello Version2.0\n)
#else printf(Hello Free Version);
#endifreturn 0;
} 运行结果 //# define VERSION1 1
//# define VERSION2 2
int main()
{
#ifdef VERSION1printf(Hello Version1.0\n);
#elif VERSION2printf(Hello Version2.0\n)
#else printf(Hello Free Version\n);
#endifreturn 0;
} 运行结果 编译过程概览 将一个.c文件翻译为可执行文件需要经过预编译prepressing) 、编译compliation、汇编assernbly、链接linking四个阶段 预编译阶段 头文件展开去掉注释宏替换条件编译 //vim编辑器编写test.c文件# include stdio.h# define M 100int main(){printf(%d\n,M); //printf(hello Linux!\n);//printf(hello Linux!\n);//printf(hello Linux!\n);printf(hello world!\n); return 0;}Linux环境使用选项 gcc -E test.c -o test.i 此条语句的含义为从现在开始进行程序的翻译过程当预处理结束时停止程序的翻译过程 上图生成test.i文件使用vim编辑器打开test.i文件 注释被删除掉宏定义的M被替换为100使用选项 vim /usr/include/stdio.h 打开c标准库对比发现头文件被替换 使用vim编辑器编写code.c代码code.c代码使用条件编译指令 //vim编辑器编写code.c代码
# define VERSION1 1
//# define VERSION2 2
int main()
{
#ifdef VERSION1printf(Hello Version1.0\n);
#elif VERSION2printf(Hello Version2.0\n)
#else printf(Hello Free Version\n);
#endifreturn 0;
} 编译阶段 1. 词法分析词法分析器处理test.i文件将字符串切割成一个个记号(mark) 例如sumab会产生五个记号sum a b 2. 语法分析语法分析器将产生的记号组织成一个个表达式以表达式为节点生成一颗语法树 3. 语义分析语义分析器处理声明以及数据类型、给语法树的节点赋予数据类型 4. 中间代码根据语法树生成中间代码以上的步骤是硬件平台无关的而中间代码之后的处理则需要根据程序运行的硬件平台来决定 5. 代码生成器代码生成器将中间代码转换成对应硬件平台的汇编代码test.s Linux环境使用选项 gcc -S test.c -o test.s 此条语句的含义为从现在开始进行程序的翻译过程当编译结束时停止程序的翻译过程 汇编阶段 汇编器汇编器根据 汇编指令与机器指令的对照表 将汇编代码翻译成机器指令生成目标文件test.o 目标文件由若干个段section组成每个段中存放不同的内容 目标文件中的基本段类型文件头、代码段、数据段、bss段、常量段、段表、符号表、重定位表 文件头文件头位于目标文件开始位置它定义了elf魔数目标文件的属性、运行的软硬件平台、程序入口地址、段表的位置及长度、段的数量 代码段存放 机器指令 数据段: 存放 已经初始化的全局变量以及静态变量 常量段存放 字符串常量以及被const修饰的变量 bss段 存放 未初始化的全局变量以及静态变量所占用的内存大小 段表 记录了目标文件中所有段的地址以及属性读写or可执行等信息 符号表记录与程序相关的所有符号如变量、函数名变量或者函数所对应的地址和属性 重定位表重定位表用于指示需要进行重定位的指令或数据记录了位置信息、长度以及对应的符号引用 Linux环境使用选项 gcc -c test.c -o test.s 此条语句的含义为从现在开始进行程序的翻译过程当汇编结束时停止程序的翻译过程 链接阶段 链接器合并输入的.o文件、确定符号内存地址、进行符号重定位输出可执行文件 Linux环境使用选项 gcc test.c -o test.exe