引言
在 ANSI C 的任何一种实现中,存在两个不同的环境。
第一种是翻译环境,在这个环境中,源代码被转换为可执行的二进制指令。
翻译环境即我们日常使用编译器,将一个 " test.c " 的文件最终变成一个 " text.exe " 的可执行文件的一个过程。
第二种是运行环境,它用于实际执行代码。
运行环境一般是由操作系统对 " test.exe " 可执行文件进行解析执行的结果。
运行环境
程序执行的过程:
① 一般来说,程序先是被操作系统载入到内存中。在独立的环境中,程序的载入也可能是通过可执行代码置入只读内存来完成。
② 程序运行开始,接着便调用 main 函数。
③ 操作系统开始执行程序代码。这个时候程序将使用一个运行时堆栈,用来存储函数的局部变量和返回地址。程序同时也可以使用静态 (static) 内存,存储于静态内存中的变量在程序的整个执行过程一直保留它们的值。
④ 终止程序。操作系统正常终止 main 函数,也有可能是意外终止。
当宏参数在宏的定义中出现超过一次的时候,如果宏参数影响本身的值,那么后续在使用这个宏的时候就可能出现不可预测的后果。按照当前的程序来看还好些,如果自增自减用的再复杂一些,你很难想象底层是怎么参与运算的。
3. #define 定义宏和函数的区别
#define 定义宏 函数
执行速度 更快 相对宏的速度较慢,函数调用和函数返回都需要开销
调试 宏不能够调试 函数可以调试
递归 宏不能够递归 函数可以递归
命名 一般宏的名字全部大写 函数名不需要全部大写
头文件包含
在引言的地方,我提到了 #include 头文件包含属于预编译的过程,它其实也是进行了相关的文本替换。但 C语言 的头文件分为两种,第一种是和库相关的库文件;第二种是本地文件包含。
如下面的程序:
注释1 为库文件包含,查找头文件的时候是直接去标准路径下去查找,如果找不到就提示编译错误。
注释2 为本地文件包含,查找策略:先在源文件所在目录下查找,如果该头文件未找到,编译器就像查找库函数头文件一样在标准位置查找头文件。如果找不到就提示编译错误。