一、程序的编译环境和执行环境
在ANSI C的任何一种实现中,存在两个不同环境:
第一种是翻译环境,在这个环境中源代码被转换为可执行的机器指令。
第二种是执行环境,它用于实际执行代码。
二、详解编译和链接
1、翻译环境
组成一个程序的每个源文件通过编译过程范别转换成目标代码(object code)。
每个目标文件由链接器(linker)捆绑在一起,形成一个单一而完整的可执行程序。
链接器同时也会引入标准C函数库中人和被该程序所用到的函数,而且他可以搜索程序员个人的程序库,将其需要的函数也链接到程序中。
预处理指令从#开始,到第一个换行符结束。
预处理指令有#define,#if ,#if defined()等
3.1、预定义符号:
在C语言中,有一些预定义符号(Predefined Symbols)是由编译器提供的,它们具有特殊的含义和功能。以下是C语言中的一些常见预定义符号:
__LINE__: 表示当前代码所在的行号。
__FILE__: 表示当前源文件的文件名。
__DATE__: 表示当前编译的日期,格式为"MMM DD YYYY",例如"Jul 29 2023"。
__TIME__: 表示当前编译的时间,格式为"HH:MM:SS",例如"10:30:36"。
__STDC__: 表示当前编译器是否符合C语言标准。如果定义了该符号,则表示编译器符合C语言标准;否则,表示不符合。
NULL: 表示空指针常量。
EOF: 表示文件结束符。
true 和 false: 表示布尔类型的真值和假值,C99引入了 <stdbool.h> 头文件来定义这两个符号。
这些预定义符号可以在代码中使用,例如用于调试、错误处理或条件编译等方面。
3.2、#under
#under指令用于“取消”已定义的#define指令。
举个例子:
#under ADD这句将移除上面#define ADD 800的定义。
移除后就可以给ADD定义一个新值了。
当然,你要是之前就没有定义过ADD,直接写#under ADD这句话也没错啦,它的定义任然是有效的。
这就又说明了C语言的方便之处,要是你想使用ADD这个常量,又不确定它之前有没有被定义过,直接上#under指令,取消一下它的定义即可。
3.3、命令行定义
许多C 的编译器提供了一种能力,允许在命令行中定义符号。用于启动编译过程。
例如:当我们根据同一个源文件要编译出不同的一个程序的不同版本的时候,这个特性便起到了作用。(假定某个程序中声明了一个某长度的数组,但是一个机器的内存有限,我们需要一个很小的数组,但是另外一个机器的内存很大,我们需要一个较大的数组。)
可以看到,代码中没有明确定义数组的大小。在编译这种代码时,我们需要使用命令行对数组的大小进行定义。
例如,在Linux环境下,编译指令如下: