⚙️ C语言 学习路线
105 个互动教程
C 语言入门 — 编程基石
C:最经典的底层语言,操作系统和嵌入式的基础
C 数组操作
数组声明/遍历/sizeof/多维数组
C语言 函数
学习函数
C typedef 类型别名
简化复杂类型声明
C 枚举 enum
定义命名整数常量组
C 数学函数 math.h
sqrt/pow/sin/cos/abs/ceil/floor
C goto 跳转
无条件跳转与错误处理模式
C printf/scanf
格式化输入输出详解
C 语言 字符串函数 — string.h
strlen/strcpy/strcat/strcmp/strtok 常用函数
C语言 typedef用法
学习typedef
C语言 运算符
学习运算符
C 指针详解
&取地址/*解引用/指针运算/数组指针
C语言 结构体
学习struct
C 动态内存分配
malloc/calloc/realloc/free
C 文件操作
fopen/fprintf/fgets/fclose
C 预处理器
#define/#ifdef/#include/#ifndef
C union 共用体
共享内存的多类型结构
C 位运算
& | ^ ~ << >> 高效位操作
C语言 文件读写
学习C语言中C语言 文件读写 — C语言教程的详细用法和最佳实践
C语言 递归函数
学习递归
C 函数深入
声明/定义/递归/static函数/函数指针
C语言 高级文件操作
C文件操作深入:fseek/ftell/rewind定位、二进制读写fread/fwrite、内存映射文件(mmap)、临时文件tmpfile、文件锁flock防止竞态
C语言 Union 联合体
C Union联合体:共用同一内存空间、大小等于最大成员、与struct对比、类型双关type punning、枚举+union实现带标签联合体、网络协议解析应用
C语言 位域 Bit Fields
C位域:在struct中按位分配成员(unsigned int flags:1)、节省内存、跨平台注意事项、与位运算配合、硬件寄存器映射、协议头解析
C语言 setjmp/longjmp 非局部跳转
setjmp/longjmp:保存/恢复执行上下文、异常处理模拟(类似try/catch)、与goto区别(跨函数跳转)、volatile变量、使用场景和陷阱(资源泄漏)
C语言 可变参数 va_list
C可变参数:stdarg.h、va_list/va_start/va_arg/va_end、实现自定义printf、默认参数提升规则、与variadic宏对比、C23可变参数改进
C语言 内联汇编
GCC内联汇编:__asm__ volatile语法、输入/输出操作数约束、clobber列表、与C变量交互、应用场景(性能关键代码/系统调用/硬件操作)
C语言 restrict 指针限定符
restrict关键字(C99):告知编译器指针不与其他指针别名(唯一访问路径)、优化SIMD向量化、与strict aliasing区别、实际性能提升场景、误用后果
C语言 原子操作 stdatomic.h
C11原子操作:stdatomic.h、atomic_int/_Atomic类型、memory_order内存序、atomic_fetch_add/atomic_compare_exchange_strong、无锁编程基础
C语言 柔性数组成员
C99柔性数组成员(FAM):struct最后一个成员int data[]不指定大小、sizeof不计算FAM、malloc(sizeof(struct)+data_size)动态分配、网络协议包/消息结构
C语言 复数类型 complex.h
C99复数:complex.h、float complex/double complex/long double complex、creal/cimag/cabs/carg/cpow、复数运算(加/减/乘/除/共轭)、FFT信号处理应用
C11 _Generic 泛型选择
C11 _Generic泛型(编译时多态):根据表达式类型选择匹配分支、实现类型安全的泛型宏(typeof-like)、创建类似C++函数重载效果、tgmath.h基于_Generic的类型泛型数学函数
C语言 内存对齐 _Alignas
C11内存对齐:_Alignas指定对齐边界、_Alignof查询类型的对齐要求、aligned_alloc对齐内存分配、struct成员对齐与填充padding、SIMD向量化对齐要求、跨平台注意事项
C语言 UTF-8 编码处理
UTF-8编码在C中的处理:UTF-8多字节编码规则(1字节ASCII/2字节/3字节(中文3字节)/4字节(emoji 4字节))、wchar_t/char16_t/char32_t宽字符类型、mbstowcs/wcstombs多字节转换、libicu/utf8proc库辅助处理Unicode规范化/大小写转换/排序
C语言 指针进阶 — 函数指针与回调
C语言函数指针:声明语法、通过指针调用函数、函数指针作为参数(回调函数)、函数指针数组(状态机)、typedef简化声明、qsort使用函数指针排序
C 多文件编译
学习如何将C程序拆分为多个源文件,并分别编译和链接。
C Makefile
学习使用Makefile自动化编译多文件C项目。
C 头文件防护
学习使用头文件防护(include guard)避免重复包含。
C static/extern
理解static和extern关键字的作用域与链接属性。
C语言 可变参数 va_list
C可变参数:stdarg.h头文件、va_list/va_start/va_arg/va_end宏、实现类似printf的函数、可变参数的限制(必须至少有一个固定参数)
C const指针
掌握const与指针的组合用法:常量指针、指针常量等。
C 变长数组
学习C99标准引入的变长数组(VLA)及其使用限制。
C 复合字面量
学习使用复合字面量创建临时数组、结构体等。
C 柔性数组
学习在结构体中使用柔性数组成员实现可变长度数据。
C setjmp/longjmp
学习使用setjmp和longjmp实现非局部跳转,模拟异常处理。
C 信号处理
学习使用signal函数处理操作系统信号,如SIGINT、SIGSEGV。
C 头文件防护机制
理解头文件重复包含的问题,学习使用 #ifndef 等预处理指令防止多重定义错误。
C const 与指针的复杂组合
厘清 const 修饰指针的不同位置(指向常量的指针、常量指针、指向常量的常量指针)及其含义。
C 多文件编译
学习如何将C程序拆分为多个源文件,并掌握编译与链接的基本流程。
C 多文件编译
学习如何将C程序拆分为多个源文件,并掌握编译与链接的基本流程。
C Makefile 入门
学习使用Makefile自动化多文件C项目的编译过程,提高开发效率。
C 头文件防护
学习使用头文件防护(include guards)避免重复包含导致的编译错误。
C static/extern 关键字
深入理解 static 和 extern 对变量和函数作用域及链接属性的影响。
C const 指针
掌握 const 与指针的组合规则,理解指针常量、常量指针和指向常量的指针常量。
C 多文件编译
学习如何将C程序拆分为多个源文件并编译链接
C语言预处理器的元编程技巧:递归宏与X-Macro
超越简单的常量定义,探索利用预处理器实现编译期代码生成、递归宏展开以及X宏模式来管理重复性数据结构。
volatile 与 const 在嵌入式寄存器映射中的精确协作
解析 volatile 和 const 在硬件寄存器声明中的组合语义,以及如何防止编译器优化破坏关键读写顺序。
C11 原子操作与内存序:构建无锁单生产者单消费者队列
深入 C11 提供的 atomic 库,重点讲解 memory_order 对 CPU 和编译器重排序的约束,实现一个高效无锁 SPSC 队列。
灵活数组成员(FAM)的底层布局与工程实践模式
深入 C99 灵活数组成员在结构体尾部的内存布局,对比指针方案的优势,以及如何安全地管理动态大小结构体。
函数指针表实现轻量级 C 面向对象:虚方法表与继承
利用结构体嵌套和函数指针表模拟 C++ 虚函数机制,实现多态与接口复用,且不引入 C++ 编译器的额外开销。
setjmp/longjmp 实现协程式协作式多任务调度
突破 setjmp/longjmp 仅用于异常处理的常规认知,利用其保存/恢复栈环境实现用户态轻量级协程切换。
位域、 packed 属性与跨字节序二进制协议序列化
结合 __attribute__((packed)) 和位域处理网络协议头部,并解决大小端转换的移植性问题。
alloca 与 VLA 的栈内存管理:性能优势与安全边界
对比 alloca 动态栈分配和 C99 VLA 的性能特征,分析栈溢出风险,并给出安全使用准则。
GCC 内联汇编约束详解:从简单指令到操作数优化
超越简单的 asm("nop"),深入理解扩展内联汇编的输入输出约束、破坏列表以及编译器优化交互。
restrict 关键字的别名分析与自动向量化优化
解释 restrict 如何允许编译器进行更积极的重排和 SIMD 向量化,并展示错误使用导致的未定义行为。
成员函数指针与虚函数调用的底层机制
深入探索 C++ 成员函数指针的内部表示,尤其是针对虚函数时多态调用的解析过程。通过手动模拟虚表索引,理解 `this` 指针调整与偏移计算。
隐式整数提升与位域的符号陷阱
解析 C 语言中整数提升规则如何与位域交互,导致意外符号扩展。重点讲解当声明为 `unsigned` 位域但表达式参与算术运算时发生的有符号提升问题。
placement new 与对象生命周期的手动控制
不依赖自动构造与析构,通过 placement new 和显式析构调用精确控制对象生存期。涵盖内存对齐要求、重复利用存储区以及避免 UB 的要点。
extern template 抑制隐式实例化与编译加速
深入 extern template 关键字如何阻止编译器在当前翻译单元隐式实例化模板,从而减少重复代码和链接时合并开销。配合显式实例化实现跨编译单元共享。
严格别名规则下的合法类型双关:memcpy 与位域
解释 C/C++ 严格别名规则禁止通过不同类型的指针读写同一内存。重点展示用 `memcpy` 实现合法类型双关,并对比 union 在不同标准下的行为差异。
变参宏与 __VA_OPT__ 的条件展开技巧
C++20 引入 `__VA_OPT__` 用于根据变参是否为空动态调整展开内容。本教程展示如何构建安全的多参数日志宏,以及当变参为空时避免尾随逗号。
不完整类型与不透明指针的封装艺术
利用不完整类型实现信息隐藏,不暴露结构体内部布局。讲解典型的 Pimpl 手法以及如何在 C 语言中使用前向声明和指针完成真正的封装。
编译期字符串处理与 consteval 强制求值
C++20 consteval 函数保证在编译期执行。结合 constexpr 字符串类,实现编译期哈希、base64 编码或字符串变换,避免运行时开销。
volatile 的真正用途:内存映射 I/O 与中断
纠正 volatile 用于多线程的误解,讲解其在嵌入式系统中读取硬件寄存器、处理信号处理程序中的共享标志等场景下的必要性和限制。
C++20 协程 Promise 类型与自定义 Awaitable 对象
深入协程框架的核心——promise_type 与 awaitable 接口。实现一个能延迟执行的协程,展示如何手动编写 promise 类型并挂起/恢复执行。
编译期断言:用静态断言在编译时发现错误
深入讲解 C23 标准引入的 static_assert 机制,以及如何在 C11/C17 中通过宏模拟,避免运行时调试开销。
restrict 限定符:向编译器承诺无别名以生成更快代码
解析 C99 引入的 restrict 关键字,说明如何通过消除指针别名假设让编译器进行更激进的循环优化与指令调度。
可变参数宏:构建类型安全的调试打印接口
利用 __VA_ARGS__ 和 __VA_OPT__(C23)设计自定义日志函数,避免标准 printf 的格式字符串不匹配问题。
线程局部存储:用 _Thread_local 避免数据竞争
详解 C11 引入的 _Thread_local 存储类说明符,在 POSIX 线程与 Windows 线程下的实现差异,以及 TLS 的正确初始化模式。
匿名结构与联合:简化嵌套数据访问
C11 标准允许在结构体或联合体中嵌入不带标签的匿名成员,直接访问内部字段,常用于协议解析与变体类型。
_Generic 泛型选择:实现编译期函数重载
C11 引入的 _Generic 关键字允许基于表达式类型在编译期选择不同代码路径,模拟 C++ 的重载与模板效果。
对齐内存分配:aligned_alloc 与 over-aligned 类型
讨论 C11 标准提供的 aligned_alloc 函数,自定义对齐要求的 struct 声明,以及如何对齐栈变量(C23 alignas)。
位精确整数类型:用 _BitInt(N) 控制位宽
C23 引入 _BitInt 类型,允许声明任意位宽的有符号/无符号整数,突破传统 char/short/int/long 的固定宽度限制,用于位级协议与紧凑存储。
原子操作与无锁编程:用 _Atomic 构建无锁数据结构
C11 原子类型(_Atomic)结合 memory_order 定义,实现无锁队列与引用计数,避免互斥锁的开销与死锁风险。
二进制资源嵌入:用 #embed 在编译期载入文件
C23 新增的 #embed 预处理指令将任意二进制文件作为字节数组直接嵌入程序,消除运行时文件读取的麻烦与安全风险。
内存屏障与volatile:突破编译器优化的迷雾
深入C语言中volatile关键字与内存屏障的配合使用,揭示多线程环境下如何防止指令重排,确保数据一致性。
restrict关键字与指针别名消除的艺术
解读C99的restrict类型限定符,如何通过承诺指针不重叠来让编译器生成更快的代码,并避免常见误用。
X宏技法:无运行时开销的枚举到字符串映射
利用X宏(X-Macro)模式自动生成枚举定义、字符串表和解析函数,避免手工维护重复代码,保持单一数据源。
编写异步信号安全的临界区:超越printf陷阱
解析POSIX信号处理中可重入函数的限制,展示如何使用sig_atomic_t和自旋锁在信号处理器中安全通信。
结构体对齐、打包与网络字节序:二进制协议解析实战
深入#pragma pack和__attribute__((packed))控制内存布局,结合htons/ntohl处理不同字节序,解析真实网络包。
alloca与VLA:栈上动态内存的高效与危险
对比alloca()和C99变长数组(VLA)的栈分配机制,讨论栈溢出检测、函数调用生命周期以及替代方案。
setjmp/longjmp实现轻量级协程调度器
利用非局部跳转模拟用户态协程,绕过函数调用栈,实现协作式多任务。讲解如何保存和恢复上下文以及限制。
复合字面量与指定初始化器:现代C的声明式编程
利用C99复合字面量创建临时结构体和数组,结合指定初始化器实现高可读性配置表,避免繁琐的逐字段赋值。
GCC内联汇编与Intrinsic函数:精确控制CPU指令
讲解asm volatile扩展语法,包括输入/输出操作数、clobber列表,以及如何用SSE/AVX intrinsic编写SIMD代码。
GCC属性魔法:构造函数与析构函数在C中的妙用
利用__attribute__((constructor))和((destructor))在main之前和之后自动执行函数,实现模块初始化/清理、自注册测试。
指针的指针实现动态二维矩阵与内存碎片规避
深入指针的二级间接访问,探讨如何用int **管理不规则二维数组,并对比与一维数组模拟二维数组的内存碎片差异。
位域与字节序:利用联合体实现跨平台协议解析
讲解位域的内存布局受字节序影响,通过联合体将位域与字节数组重叠,演示如何编写可移植的网络协议解析代码。
Restrict关键字:通过别名声明让编译器自动向量化
揭示restrict作为C99的关键字如何断言指针无别名,使编译器生成SIMD指令。对比有无restrict的汇编差异。
变参宏的__VA_ARGS__与##__VA_ARGS__扩展技巧
深入变参宏的定义、##的粘贴作用以及空参数处理,实现类似printf的日志宏并支持格式化字符串。
setjmp/longjmp实现轻量级协程切换
利用非局部跳转实现协作式多任务,保存和恢复栈环境,模拟简单协程调度,揭示栈帧指针操作。
柔性数组成员:变长结构体设计与内存连续布局
讲解C99柔性数组成员(flexible array member)的语法、sizeof计算、与指针方案的内存连续性差异。
对齐与packed属性:手动控制结构体布局避免硬件异常
探讨默认对齐、__attribute__((packed))、aligned属性对结构体大小的影响,以及未对齐访问在ARM上的fault。
Goto统一错误处理:资源释放的经典模式与替代方案
讲解使用goto进行集中式错误清理(如文件关闭、内存释放),对比do-while(0)与函数包装的优劣。
静态断言:在编译期检测结构体大小与数组边界
讲解static_assert(C11 _Static_assert)的用法,用于在编译期验证 sizeof、枚举值范围、平台假设等。
计算goto与标签指针:构建超高效状态机
利用GCC扩展的标签指针(&&label)和计算goto,实现跳转表驱动的状态机,比switch-case更快。