【第 1 章 初识 C 语言】1.6 C 语言标准:C89/90、C99、C11、C17、C23
目录
1.6 C 语言标准
1.6.1 第 1 个 ANSI / ISO C 标准
1.6.2 C99 标准
1.6.3 C11 标准
1.6.4 C17 标准
1.6.5 C23 标准
1.6 C 语言标准
目前,有许多 C 实现可用。在理想情况下,编写 C 程序时,假设该程序中未使用机器特定的编程技术,那么它的运行情况在任何实现中都应该相同。要在实践中做到这一点,不同的实现要遵循同一个标准。
C 语言发展之初,并没有所谓的 C 标准。1987 年,布莱恩·柯林汉(Brian Kernighan)和丹尼斯·里奇(Dernis Ritchie)合著的 The C Programming Language (《C语言程序设计》)第 1 版是公认的 C 标准,通常称之为 K&R C 或经典 C。
特别是,该书中的附录中的 “C 语言参考手册” 已成为实现 C 的指导标准。例如,编译器都声称提供完整的 K&R 实现。虽然这本书中的附录定义了 C 语言,但却没有定义 C 库。
与大多数语言不同的是,C 语言比其他语言更依赖库,因此需要一个标准库。实际上,由于缺乏官方标准,UNIX 实现提供的库已成为了标准库。
1.6.1 第 1 个 ANSI / ISO C 标准
随着 C 的不断发展,越来越广泛地应用于更多系统中,C 社区意识到需要一个更全面、更新颖、更严格的标准。
鉴于此,美国国家标准协会(American National Standards Institute,ANSI)于 1983 年组建了一个委员会(X3J11),开发了一套新标准,并于 1989 年正式公布。该标准(ANSI C)定义了 C 语言和 C 标准库。国际标准化组织(International Organization for Standardization,ISO)于 1990 年采用了这套 C 标准(ISO C)。
ISO C 和 ANSI C 是完全相同的标准。ANSI / ISO标准的最终版本通常叫作 C89(因为 ANSI 于 1989 年批准该标准)或 C90(因为 ISO 于 1990 年批准该标准)。另外,由于ANSI 先公布 C 标准,因此业界人士通常使用 ANSI C。
在该委员会制定的指导原则中,最有趣的可能是:保持 C 的精神。委员会在表述这一精神时列出了以下几点:
- 信任程序员;
- 不要妨碍程序员做需要做的事;
- 保持语言精练简单;
- 只提供一种方法执行一项操作;
- 让程序运行更快,即使不能保证其可移植性。
在最后一点上,标准委员会的用意是:作为实现,应该针对目标计算机来定义最合适的某特定操作,而不是强加一个抽象、统一的定义。在学习 C 语言过程中,许多方面都反映了这一哲学思想。
1.6.2 C99 标准
1994 年,ANSI / ISO 联合委员会(C9X 委员会)开始修订 C 标准,最终发布了 C99 标准。该委员会遵循了最初 C90 标准的原则,包括保持语言的精练简单。委员会的用意不是在 C 语言中添加新特性,而是为了达到新的目标。
- 第 1 个目标是,支持国际化编程。例如,提供多种方法处理国际字符集。
- 第 2 个目标是,“调整现有实践致力于解决明显的缺陷”。因此,在遇到需要将 C 移至 64 位处理器时,委员会根据现实生活中处理问题的经验来添加标准。
- 第 3 个目标是,为适应科学和工程项目中的关键数值计算,提高 C 的适应性,让 C 比 FORTRAN 更有竞争力。
这 3 点(国际化、弥补缺陷和提高计算的实用性)是主要的修订目标。在其他方面的改变则更为保守,例如,尽量与 C90、C++ 兼容,让语言在概念上保持简单。用委员会的话说:“……委员会很满意让 C++ 成为大型、功能强大的语言”。
C99 的修订保留了 C 语言的精髓,C 仍是一门简洁高效的语言。本书指出了许多 C99 修改的地方。虽然该标准已发布了很长时间,但并非所有的编译器都完全实现 C99 的所有改动。因此,你可能发现 C99 的一些改动在自己的系统中不可用,或者只有改变编译器的设置才可用。
1.6.3 C11 标准
维护标准任重道远。标准委员会在 2007 年承诺 C 标准的下一个版本是 C1X,2011 年终于发布了 C11 标准。此次,委员会提出了一些新的指导原则。出于对当前编程安全的担忧,不那么强调 “信任程序员” 目标了。
而且,供应商并未像对 C90 那样很好地接受和支持 C99。这使得 C99 的一些特性成为 C11 的可选项。因为委员会认为,不应要求服务小型机市场的供应商支持其目标环境中用不到的特性。
另外需要强调的是,修订标准的原因不是因为原标准不能用,而是需要跟进新的技术。例如,新标准添加了可选项支持当前使用多处理器的计算机。
对于 C11 标准,我们浅尝辄止,深入分析这部分内容已超出本书讨论的范围。
注意:
本书使用术语 ANSI C、ISO C 或 ANSI / ISO C 讲解 C89/90 和较新标准共有的特性,用 C99 或 C11 介绍新的特性。有时也使用 C90(例如,讨论一个特性被首次加入 C 语言时)。
扩展:
除了广为人知的 C89/C90、C99 和 C11 标准之外,C 语言标准持续演进。以下是对后续的 C17 和 C23 标准的简要介绍,值得适当关注。
1.6.4 C17 标准
C17,正式名称为 ISO/IEC 9899:2018,是 C 语言的最新国际标准之一,于 2018 年发布。它作为对 C11 标准的技术修正版,主要目标是对现有标准进行清理和修正,以提高其可读性和一致性,而不是引入大量新的功能或特性。因此,C17 可以被视为一个 “维护版本”,旨在修复和澄清 C11 中存在的问题。主要修改内容如下:
- 移除过时功能:C17 移除了某些过时的功能,例如对 gets() 函数的支持,因为该函数存在安全风险。
- 新增宏定义:引入了如 __STDC_WANT_LIB_EXT1__ 等宏,用于控制是否启用可选的库扩展。
- 改进的对齐支持:增强了对齐和原子操作相关的功能,提供了更好的内存管理和并发编程支持。
- 标准化改进:对标准库进行了微调,包括对 <stdatomic.h> 和 <threads.h> 的改进。
- 文本和技术修正:修正了标准文档中的不一致性和错误,提高了规范的清晰度和准确性。
- 删除 trigraphs:三字符组合(trigraphs)在 C17 中被移除,简化了预处理器的行为。
对于大多数开发者来说,从 C11 升级到 C17 不需要对代码做重大更改。C17 更多地关注于改善语言的一致性和稳定性,确保编译器实现更加可靠。尽管新特性不多,但对于追求代码质量和安全性的开发团队而言,这些改进仍然是有价值的。
1.6.5 C23 标准
C23,正式名称为 ISO/IEC 9899:2023,是 C 语言最新的国际标准版本,于 2023 年发布。C23 在保持与先前版本向后兼容的同时,引入了多项新特性和改进,旨在使 C 语言更加现代化、安全和高效。主要新增特性如下:
- 泛型编程支持:通过扩展 _Generic 关键字,增强了对泛型编程的支持,使得编写更加通用的代码成为可能。
- 类型安全性增强:引入了新的类型属性如 _Noreturn 和改进的 _Static_assert,帮助开发者在编译时捕获更多类型的错误。
- Unicode 支持改进:新增了 _UTF8、_UTF16 和 _UTF32 字符串前缀,以更好地支持 Unicode 字符串,满足国际化需求。
- 线程支持标准化:虽然具体实现仍依赖于编译器和操作系统,但 C23 对线程库进行了标准化,提供了更一致的多线程编程接口。
- 错误处理机制优化:改进了错误处理机制,包括引入了新的函数和宏,以提供更强大的异常处理能力。
- 内存模型和原子操作增强:进一步优化了内存模型,特别是关于并发编程中的原子操作,提高了多线程应用的安全性和效率。
- 标准化可变参数宏:对<stdarg.h> 的改进,增加了对可变参数宏更好的支持。
- 浮点数处理改进:对浮点数处理函数进行了扩展,增加了更多的数学运算功能。
- 文本和技术修正:修正了标准文档中的不一致性和错误,提高了规范的清晰度和准确性。
C23 标准不仅增强了 C 语言的功能,还显著提升了其安全性和易用性。对于开发者来说,这意味着可以利用更先进的特性来构建复杂且高性能的应用程序,同时减少了潜在的错误和安全隐患。对于需要跨平台开发或关注代码质量的团队而言,这些改进尤为重要。