- 程序的翻译环境和执行环境
- 编译+链接
- 预处理
一.程序的翻译环境和执行环境
在ANSI C标准的任何一种实现中,存在两种不同的环境:
- 翻译环境:该环境中 源代码 会被转换为 可执行的机器指令
- 执行环境:其用于实际 执行代码
二.编译+链接
2.1翻译环境
- 一个源文件经过编译器处理形成一个目标文件,目标文件被链接器链接形成可执行程序
- 翻译环境是 编译 和 链接
2.2翻译环境的几个阶段
2.3运行环境
程序执行的过程:
- 程序必须载入内存中。
在有操作系统的环境中:程序的载入一般由操作系统完成。
在独立环境中:程序的载入必须手工安排,也可能是通过可执行代码置入只读内存来完成。
2.程序的执行便开始。接着便调用 main 函数。
3.开始执行程序代码,这个时候程序将使用一个运行时堆栈(stack),存储函数的局部变量和返回地址。程序同时也可以使用静态(staic)内存,存储于静态内存中的变量在程序整个执行过程中一直保留它们的值。
4.终止程序。正常终止main函数,也可能是意外终止
三.预处理
3.1预定义符号
- 在预处理阶段被处理的已经定义好的符号,可以拿来直接用
- 左下和右下都是2个下划线
- 如果一个工程特别复杂,这时去调试时可能会无从下手。所以需要代码在运行的过程中记录一些日志信息,即可通过日志信息看程序哪里出了问题
例子:
- 除以上5个外,还有一个 __STDC__,如果编译器遵循 ANSI C 标准则返回1,否则未定义
在Dev-c++上有1,表明其遵循 ANSI C 标准
3.2#define
3.2.1 #define 定义标识符
语法:
注意:#define 定义标识符 ,其末尾不用再加个分号
例子:
3.2.2 #define 定义宏
- #define 机制有个规定,允许把参数替换到文本中,这种实现成为宏或定义宏
申明方式:
举例:
// 先将函数中name()中的参数替换 掉宏中的参数,再将stuff的结果返回函数去 替换掉name()
特别注意:宏的参数是完全替换的,不事先计算再传参
例子:用类似上述方法得出16
//这样明显不对,So在敲的时候我们可以带上()来防止出错
注意下面这种情况:
3.2.3 #define 替换规则
在程序中扩展#define定义符号和宏时,几个步骤:
- 在调用宏时,首先对参数进行检查,看是否包含任何由 #define 定义的符号。如果是,它们先被替换
- 替换文本随后被插入到程序中原来的文本位置。对于宏,函数名被它们的值替换
- 再次对结果文件进行扫描,看是否包含任何由 #define 定义的符号。如果包含,就重复上述过程。
注意:
- 宏参数 和 #define 定义中可以出现其他 #define 定义的常量。但对于宏,不能出现递归
- 当预处理器 搜索 #define 定义的符号的时候,字符串常量中的内容不被搜索,即不会被替换
3.3命名约定
由于一般来讲,函数和宏的使用语法相似,所以为了区分它们,用一个习惯是:宏名全部大写,函数名不要全部大写
3.4#undef
该命令用于 移除一个宏定义
语法格式:
例子:
3.5 条件编译
在编译一个程序时,可以用条件编译将一条语句或一组语句编译/放弃是很方便的
//如果定义了则会编译 ,没有定义则不会参与编译