2024年10月9日 12:30

This commit is contained in:
许大仙 2024-10-09 04:30:15 +00:00
parent b04a2ecf24
commit 27515bfbf2

View File

@ -95,27 +95,54 @@
## 1.4 为什么 C 语言需要预处理?
* C 语言并没有一个官方机构,也不属于哪个公司,它只有一个制定标准的委员会,任何其他组织或者个人都可以开发 C 语言的编译器,而这个编译器要遵守哪个 C 语言标准,是 100% 遵守还是部分遵守,并没有强制性的措施,也没有任何约束。
### 1.4.1 概述
* 在实际开发中,有的时候,我们希望自己编写的程序能够跨平台(操作系统)运行,但是可能每个平台提供的系统库函数不同,如:在 Windows 上实现暂停的函数是 `void Sleep(DWORD dwMilliseconds)`,单位是 `ms`,头文件是 `<windows.h>`;而 Linux 上实现暂停的函数是 `unsigned int sleep (unsigned int seconds)`,单位是 `s` ,头文件是 `<unistd.h>`。所以,我们希望在 Windows 上调用的是 `Sleep()` 函数,而在 Linux 上调用的是 `sleep()` 函数,怎么办?
* 这就需要在编译之前对源文件进行处理:如果检测到的平台是 Windows就保留 `Sleep()` 函数而删除 `sleep()` 函数;反之,如果检测到的平台是 Linux则保留 `sleep()` 函数而删除 `Sleep()` 函数。
> [!NOTE]
>
> - ① 各个厂商可以根据自己的利益和喜好来开发编译器
> - ② 市场和用户的选择通常是推动编译器开发者遵循标准的主要动力。
> * ① 这些在编译之前对源文件进行简单加工的过程,就称为`预处理`,即:预先处理、提前处理
> * ② 之前提过,在 Windows 上推荐使用 `MSYS2` ,就是因为 `MSYS2` 提供了一个兼容层,使得在 Windows 上可以使用类似于 Linux 的环境。并且,`MSYS2` 同时支持 Windows 和类 Unix 的库函数,对我们开发跨平台程序更为友好!!!
* 并且,不同硬件平台之间也存在差异,这会导致内存管理方式、寄存器、指令集等都有所不同,为了确保 C 语言程序能在这些硬件平台运行,就得针对该平台开发/定制不同的编译器。
### 1.4.2 应用示例
* 需求:开发一个 C 语言程序,让它暂停 5 秒以后再输出内容,并且要求跨平台。
> [!NOTE]
>
> - ① 上述的情况,在单片机和嵌入式领域更加常见。
> - ② 总体而言C 语言具有开放性,并且要适应不同的硬件平台,这使得不同厂商可以根据自己的需求来进行个性化开发/定制。
* 这也导致了一个非常棘手的问题,有的编译器遵守较新的 C 语言标准,有的编译器只能遵守较老的 C 语言标准,有的编译器还进行了很多扩展,比如:
* GCC、LLVM/Clang 更新非常及时,能够支持最新的 C 语言标准。
* MSVC 更新比较缓慢迟迟不能支持新标准例如VC6.0、VS2010 都在使用 C89 标准VS2015 部分支持 C99 标准。
> [!NOTE]
> 不同平台下的暂停函数和头文件都不一样,如下所示:
>
> 微软官方给出的答复:最新的标准已经在 C++ 中支持了C 语言就没必要再重复了。
> * ① Windows 平台下的暂停函数的原型是`void Sleep(DWORD dwMilliseconds)`(注意 S 是大写的),参数的单位是 `ms`,位于 `<windows.h>` 头文件。
> * ② Linux 平台下暂停函数的原型是`unsigned int sleep (unsigned int seconds)`,参数的单位是 `s`,位于 `<unistd.h>` 头文件。
* 示例:
```c
#include <stdio.h>
// 不同的平台下引入不同的头文件
#if _WIN32 // 识别windows平台
#include <windows.h>
#elif __linux__ // 识别linux平台
#include <unistd.h>
#endif
int main() {
// 不同的平台下调用不同的函数
#if _WIN32 // 识别windows平台
Sleep(5000);
#elif __linux__ // 识别linux平台
sleep(5);
#endif
puts("Hello World\n");
return 0;
}
```