浅析C语言标准及特性

文章目录

概述

C语言发展之初,并没有正式的标准。1978年,布莱恩•柯林汉和丹尼斯•里奇合著的C语言程序设计》第一版被公认为是C语言最早的标准,通常也被称为K&R C。随着C语言的不断发展,第一个C语言正式标准,即ANSI C,于1989年发布,这是目前使用最广泛的版本,也称C89。后续C标准继续修订并加入新的特性,陆续又发布了C99、C11等标准,最新的C标准已经到了C23。

C标准发展历程

C标准发展史编排如下:

C标准 发布时间 描述
ANSI C 1989 由美国国家标准协会(ANSI)开发,定义了C语言和C标准库,也称C89
ISO C 1990 由国际标准化组织(ISO)发布,是与ANSI C完全相同的标准,也称C90
C99 1999 C标准委员会对C语言不断改进,并收纳为新的标准,于1999年正式发布,简称C99,也是严格意义上C语言的第二个正式版本
C11 2011 C标准委员继续对C语言进行改进,并收纳为新的标准,于2011年正式发布,简称C11
C17/C18 2017 C17/18主要是C11标准错误的修正,无新特性引入,于2017年发布
C23 2023 现代化C语言,也是最新的C语言标准,简化语法,增强安全,同时删除了大量旧时的特性,于2023年发布

GCC编译器扩展

除了C语言官方发布的标准,例如GCC编译器也会提供额外的非标准语言特性支持,这些扩展特性被加入到了编译器的选项中,可以由用户指定编译选项进行使用。GCC编译器的C标准实现包括gnu89、gnu99、gnu11等,可以统称为GNU C标准,本质上就是对应版本的C语言标准特性+编译器扩展特性的合集。关于GNU C标准的扩展特性,可以通过查看GCC工具手册进行了解,编程人员可以通过制定-std=选项来选择特定的标准使用。

ANSI C标准

作为C语言的第一个正式标准,ANSI C定义了C语言的基础语言特性以及标准库相关的内容。ANSI C包含的语言特性如下:

  • 关键字:ANSI C一共定义了32个关键字,包含数据类型、存储类别等,是C语言初代标准关键字集合。
  • 语法基础:定义了分支、循环、跳转等基础语句语法,支持指针、数组、函数以及预处理等功能;
  • C语言标准库

ANSI C标准关键字

关键字 描述
auto 声明自动局部变量,默认存储类别
break 跳出循环或switch分支
case switch语句分支匹配标签
char 字符基础数据类型
const 修饰只读常量,变量不可修改
continue 终止当前本轮循环,直接进入下一轮循环
default switch分支无匹配时执行的默认分支
do do-while循环起始标识
double 双精度浮点数据类型
else if条件不满足时执行的分支
enum 定义枚举自定义数据类型
extern 声明外部全局变量或外部函数
float 单精度浮点数据类型
for for循环语句关键字
goto 无条件跳转到代码自定义标签处
if 条件判断语句关键字
int 基础整型数据类型
long 长整型修饰符,扩大数值存储范围
register 建议编译器将变量存入CPU寄存器,提升读取速度
return 函数返回数据,终止当前函数运行
short 短整型修饰符,缩小整型占用字节
signed 有符号修饰符,变量可存储正负数值
sizeof 单目运算符,计算类型/变量占用内存字节数
static 静态修饰:局部变量生命周期延长;全局变量仅当前文件可见
struct 定义结构体复合数据类型
switch 多分支条件匹配语句
typedef 为已有数据类型自定义别名
union 定义共用体(联合体)数据类型
unsigned 无符号修饰符,变量仅存储非负数
void 空类型:无返回值、无函数参数、通用空指针
volatile 禁止编译器优化该变量,变量值可能被硬件/外部程序修改
while while循环、do-while循环尾部条件判断

C99标准

C99新增关键字

C99标准新增5个关键字:inline、restrict、_Bool、_Complex、_Imaginary,各个关键字的含义如下:

关键字 含义
inline 用于指示编译器尽可能地将inline修饰的函数指令在被调用的地方展开
restrict 用于指针修饰,表明该指针是访问其管理数据的唯一方式
_Bool C99新增_Bool类型,用于表示布尔值,对应于逻辑值true和false
_Complex 复数类型
_Imaginary 虚数类型

C99新增特性

语法与变量定义
特性 描述
// 单行注释标准化 C89仅编译器扩展,C99正式纳入标准
代码块任意位置定义变量 C89仅允许在代码块起始处定义变量
for循环头部定义局部变量 在for()内声明变量,作用域仅循环内部
long long / unsigned long long 64位整型,配套 LL、ULL 数值后缀
变长数组 VLA 数组长度使用运行时变量,栈内存分配
复合字面量 临时构造数组、结构体等匿名对象
指定初始化 结构体/数组按成员名赋值,无需按顺序
灵活数组成员 结构体末尾无长度数组,适配动态内存分配
空大括号零初始化 = {} 数组、结构体支持空括号整体清零
VLA函数形参 int arr\* 变长数组函数声明简写语法
复合字面量可作为返回值 临时结构体、数组可直接return返回
弱化隐式int规则 无返回类型函数默认int被标记为过时写法
预处理与编译内置
特性 描述
可变参数宏 VA_ARGS 宏定义支持不定数量输入参数
func 内置标识符 字符串常量,自动存储当前函数名称
十六进制浮点常量 支持 0x1.2p3 格式浮点数字面量
新增标准头文件与类型
特性 描述
<stdint.h> 提供固定位宽整数:uint8_t、int32_t等
<stdbool.h> 封装 bool、true、false 简化布尔编码
<tgmath.h> 泛型数学库 同一函数自动适配 float/double 浮点类型
<wchar.h> 宽字符库 统一宽字符、多字节字符转换接口
标准库与格式化输出
特性 描述
%zu、%td 格式化占位符 分别用于打印 size_t、ptrdiff_t 类型
新增大量数学库函数 round、erf、tgamma、nearbyint 等浮点函数

C11标准

C11新增关键字

C11标准新增7个关键字:Alignas、_Alignof、_Noreturn、_Generic、_Thread_local、_Atomic、_Static_assert,各个关键字含义如下:

关键字 描述
Alignas 内存对齐的操作符,与_Alignof配合使用,指定结构的对齐方式
_Alignof 获取类型和变量的对齐方式
_Noreturn 修饰函数,不会返回值
_Generic 泛型函数
_Thread_local 线程局部存储,限定了变量不能在多线程之间共享
_Atomic 原子操作
_Static_assert 编译期间断言

C11新增特性

语法与类型扩展
特性 描述
匿名结构体 / 匿名联合体 结构体内部无名称的嵌套结构,可直接访问内层成员,简化协议、寄存器定义
max_align_t 代表系统基础类型最大对齐粒度,malloc 分配内存默认满足该对齐
变长数组VLA改为可选特性 C99强制支持,C11标准改为可选,编译器可选择不实现
并发、原子、多线程
特性 描述
<threads.h> 多线程标准库 标准化线程创建、互斥锁、条件变量、一次性初始化
<stdatomic.h> 原子操作库 原子类型、原子读写、内存序,无锁并发编程标准接口
标准化内存模型 定义多线程数据竞争、可见性、执行顺序规则
thrd_t、mtx_t、cnd_t 线程、互斥锁、条件变量标准类型
call_once 一次性执行 保证一段代码在多线程环境仅执行一次,用于单例初始化
标准库变更与安全优化
特性 描述
彻底移除 gets() 存在严重缓冲区溢出漏洞,永久删除,推荐 fgets
fopen 新增独占模式 "x" fopen("a.txt", "wx"),文件不存在才创建,防止覆盖已有文件
新增安全边界字符串函数 strnlen、strndup 等,限制操作长度避免越界
快速退出 quick_exit() 不执行静态对象析构、仅注册atexit_at_quick回调,快速终止程序
at_quick_exit() 注册 quick_exit 触发时执行的回调函数
预处理与兼容性调整
特性 描述
移除隐式函数声明支持 调用未声明函数强制警告/报错,杜绝未定义行为
支持UTF-8字符字面量 u8"" 原生UTF-8字符串常量,区分于宽字符
修复复合字面量、初始化边界定义 统一数组、结构体初始化未定义填充规则

C23标准

C23标准新增关键字

关键字 功能描述
nullptr 标准空指针常量,类型为 nullptr_t,区分整数0
static_assert 升级为关键字,替代 C11 的 _Static_assert,无需头文件
bool 内置布尔关键字,无需包含 <stdbool.h>
true 布尔真值字面量,内置关键字
false 布尔假值字面量,内置关键字
typeof 编译期获取表达式/变量的类型,简化泛型代码
loop 标签循环配套关键字,支持带标签break跳出外层循环

相关参考

  • 《C Primer Plus》
  • 《C语言深度剖析》