环境
1. 翻译环境与执行环境
C 语言将一个程序的处理和运行划分在两个不同的环境中:翻译环境(Translation Environment)与执行环境(Execution Environment)。
1. 翻译环境(编译阶段:静态检查)
- 职责:负责把人写好的 C 源代码,经过预处理、编译、汇编和链接,最终翻译成机器能够识别的二进制可执行文件。
- 编译器的角色:此时编译器只进行静态检查,包括语法是否正确、类型是否匹配、静态约束是否被违反等。
- 局限性:编译器无法预测运行时的具体数据。
2. 执行环境(运行阶段:动态表现)
- 职责:目标程序在目标平台上执行。
- 在宿主环境(有操作系统,如 Linux、Windows)中,程序由操作系统加载并运行。
- 在独立环境(无操作系统,如单片机裸机、内核开发)中,程序直接在硬件上复位并运行。
- 运行时的表现:此时程序开始产生动态行为,例如与用户进行输入输出(I/O)交互、向系统申请动态内存、进行多线程调度等。
- 错误的发生:很多问题只有在程序跑起来、数据真正流动时才会暴露出来。
2. 宿主实现与独立实现
C 语言中,实现是一套特定的软件,它在特定的翻译环境下运行(并受特定控制选项影响),执行程序的翻译工作,并支持函数在特定的执行环境中执行。通常指编译器 + 标准库 + 目标运行平台。在宿主实现 (Hosted Implementation) 中,有操作系统支持(比如你现在学 C 语言使用的编译器,还有你电脑上搭载的操作系统);在独立实现 (Freestanding Implementation) 中,则没有。
1. 宿主实现
只要你写的是一个严格符合 C 标准的程序,宿主实现就必须无条件接受并成功运行它。此时,你可以畅通无阻地使用所有的 C 标准库,比如写 printf、用 malloc。
PS:我相信几乎所有读者使用的都是宿主实现。
2. 独立实现
由于独立环境没有操作系统支持,它无法提供像 printf(需要文件系统和屏幕驱动)或 malloc(需要复杂的系统内存管理)这样的高级功能。
但只要你写的程序足够简单(只依赖标准库当中的一小部分),那么独立实现也得保证必须能够成功编译并运行它。
可通过以下方式判断使用的是何种实现:宿主实现输出 1,独立实现输出 0。
c
#include <stdio.h>
int main(void) {
#ifdef __STDC_HOSTED__
printf("__STDC_HOSTED__ = %d\n", __STDC_HOSTED__);
#endif
return 0;
}1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
可能的输出(示例):
bash
1
当输出为 1 时,表示按宿主环境处理;为 0 时,表示独立环境。这个宏不能替代完整平台文档,但可以作为源码中的清晰分支条件。