编译2:预处理和编译
预处理:
预处理是在编译之前,先处理掉源码中的预处理命令,如#include、#define
编译器是不认识这些预处理命令的,若不先处理会在编译阶段报错
预处理的过程包括:
- #include头文件展开到当前位置
- #define宏展开,并删除#define
- 条件编译,选择需要编译的分支,丢弃不需要的分支
- 删除注释
- 添加行号和文件名标识
- 保留#pragma命令,用于编译时指示编译器执行特殊行为
使用预处理命令的好处:
- 头文件包含实现模块化编程
- 宏定义提高代码可读性
- 条件编译增强代码兼容性
- #pragma命令可以指示编译器执行特殊行为
常见预处理命令:
#include头文件包含
#define定义宏
#define //定义一个预处理宏
#undef //取消宏的定义
#if、#else、#endif、#ifdef、#ifndef条件编译
#if //编译预处理中的条件命令,相当于C语法中的if语句
#ifdef //判断某个宏是否被定义,若已定义,执行随后的语句
#ifndef //与#ifdef相反,判断某个宏是否未被定义
#elif //若#if, #ifdef, #ifndef或前面的#elif条件不满足,则执行#elif之后的语句,相当于C语法中的else-if
#else //与#if, #ifdef, #ifndef对应, 若这些条件不满足,则执行#else之后的语句,相当于C语法中的else
#endif //#if, #ifdef, #ifndef这些条件命令的结束标志.
defined //与#if, #elif配合使用,判断某个宏是否被定义,defined(name): 若宏被定义,则返回1,否则返回0。
#pragma编译控制
#pragma pack([n]) //指示结构体联合体成员的对齐方式
#pragma message("string") //在编译器输出窗口打印文本消息
#pragma warning //有选择地改变编译器警告行为
#pragma once //防止头文件多次编译
编译:
编译就是将.c文件转换成.s的汇编文件的过程。
在这个过程中,c文件中的代码块、函数将转换成代码段;全局变量、静态变量、常量转换成数据段;
编译过程如下:
- 词法分析
- 语法分析
- 语义分析
- 中间代码生成
- 汇编代码生成
- 目标代码生成