第一部分 预处理命令一、gcc 编译 C 程序的四个阶段完整编译流程分为预处理、编译、汇编、链接四步每一步有独立操作与输出文件预处理阶段执行对应指令后生成后缀为.i 的文件。仅处理所有以 #开头的预处理相关内容不做语法运算只做文本展开替换展开所有引入的头文件内容、全局替换宏定义文本、根据条件编译规则筛选需要参与编译的代码。编译阶段基于预处理后的文件生成后缀为.s 的汇编文件。核心工作是将 C 语言逻辑转换为汇编指令同时完成语法、语义检查程序基础报错会在这一步触发。汇编阶段基于汇编文件生成后缀为.o 的二进制目标文件。将汇编指令转换成计算机可识别的二进制机器码此时文件仅包含当前程序自身代码缺少库函数的完整实现地址。链接阶段整合目标文件生成最终可执行程序。核心作用是链接系统标准库补齐 printf 等库函数底层实现地址同时合并多个目标文件生成能够直接运行的程序。二、宏定义宏属于预处理指令仅在预处理阶段做纯文本替换不会进行计算、不会分配内存分为无参宏与带参宏两类。无参宏符号常量用于定义固定常量规范写法建议宏标识符全部大写定义末尾不能添加分号。为避免运算优先级出错常量内容整体建议用括号包裹。带参宏宏函数外观类似函数但本质依旧是文本替换。宏的参数、整体表达式都必须加括号防止运算符优先级导致逻辑错误。宏核心注意事项仅文本替换无参数类型检查、无运行计算逻辑宏会直接展开文本多次调用会增大程序整体体积和普通函数区分函数在程序运行时调用需要保护、恢复现场存在调用开销不会增加代码体积。三、头文件包含规则头文件内一般存放其他头文件引用、自定义数据类型、宏定义、函数与全局变量声明不建议存放函数实现。两种包含格式查找逻辑完全不同尖括号格式代表系统标准头文件编译器直接从系统内置头文件路径搜索双引号格式代表用户自定义头文件编译器优先从当前代码所在文件夹查找找不到再检索系统路径。四、条件编译通过宏是否定义、表达式真假选择性编译部分代码三大常用场景防止头文件重复包含固定三段式结构判断宏是否未定义未定义则定义该宏并写入头文件内容避免多次引入同一个头文件造成重复定义报错。按表达式条件编译通过逻辑表达式结果控制代码是否参与编译常用写法是表达式写 0中间代码会直接屏蔽用于临时注释大段代码。按宏是否定义编译分为 ifdef 与 ifndef 两种ifdef 判断宏已经定义则编译对应代码ifndef 判断宏未定义则编译对应代码两者都可搭配 else 实现二选一编译逻辑。第二部分 指针一、基础概念内存程序运行时可使用的存储空间计算机以字节为单位给每一块内存分配唯一编号地址内存字节对应的唯一编号指针地址本身用来标记一块内存空间的位置指针变量专门用来存储内存地址的变量自身会占用固定内存空间。二、指针变量定义规则定义格式由两部分组成基类型、指针标识、变量名。基类型限定指针指向内存中存储数据的类型决定取值时读取多少字节星号为指针类型标识代表该变量是指针变量名遵循标识符规范行业习惯以 p 开头命名指针变量。指针变量内存大小指针存储的是内存地址占用空间由操作系统位数决定和指向的数据类型无关64 位系统所有指针占 8 字节32 位系统所有指针占 4 字节。三、指针初始化与野指针合法初始化两种方式赋值为空指针 NULL赋值已有普通变量的地址野指针没有初始化、或者指向已经释放销毁内存的指针访问野指针会引发程序崩溃规避野指针方法定义指针时统一初始化为空指针使用前确保指向合法有效变量地址。四、两个核心运算符取值运算符 *放在指针变量前方用于读取该指针存储地址对应的内存数据运算后表达式类型降级为指针的基类型。读取字节数由基类型决定char 类型指针读取 1 字节int 读取 4 字节double 读取 8 字节。使用限制仅能作用于指针变量不能作用于普通数值。取地址运算符 放在普通变量前方获取该变量存储空间首字节地址。使用限制只能对变量取地址常量、运算表达式不能使用取地址符。五、指针算术运算加减乘除取模中只有加减自增自减有实际意义乘除取模无使用价值指针自增 / 自减 --向后 / 向前偏移一块基类型大小的内存char 指针 ±1 偏移 1 字节int 指针 ±1 偏移 4 字节两个同类型指针相减计算两个地址之间相隔的元素个数等于地址字节差值除以基类型占用字节禁止两个指针相加无实际业务逻辑。六、指针作为函数参数修改主函数内原始变量必须传递变量地址函数内通过指针取值修改原空间数据仅读取主函数变量数据既可以传递普通值也可以传递地址函数返回多组计算结果将主函数定义变量的地址传入函数函数内通过指针写入结果。七、一维数组与指针数组名本质是数组首元素的地址属于地址常量不允许直接赋值修改数组下标写法与指针写法完全等价数组第 n 个元素可以通过数组名偏移 n 再取值实现一维数组作为函数参数两种等价写法数组形式参数、同类型指针参数底层均传递数组首元素地址。