【C陷阱与缺陷】第8章编程建议总结 | 写出更健壮的C代码在底层的角度下一个程序就是一个由符号(token)或者记号组成的序列就像一本书(程序)也只是一个单词(token)序列。还可以把程序看作语句和声明的序列就像可以把书看作句子的序列一样。把程序分割成符号的过程叫做词法分析。写作本书的出发点不是要批判C语言而是帮助C程序员绕过编程过程中的陷阱和障碍。全书分为8章分别从词法分析、语法语义、连接、库函数、预处理器、可移植性缺陷等几个方面分析了C编程中可能遇到的问题。最后作者用一章的篇幅给出了若干具有实用价值的建议。(关注不迷路哈)文章目录【C陷阱与缺陷】第8章编程建议总结 | 写出更健壮的C代码前言一、不要自我欺骗认清现实典型示例问题分析建议二、明确表达意图代码即文档1. 使用括号明确优先级2. 常量在左的比较技巧建议三、考查边界情况简单特例验证重要原则示例数组处理建议四、使用不对称边界统一处理模式核心思想示例循环处理建议五、警惕隐藏的Bug了解语言特性1. 避免生僻特性2. 注意移植性问题建议六、防御性编程假设最坏情况1. 验证输入假设2. 检查边界条件3. 处理可能的错误建议七、综合编程准则八、全书总结前言《C陷阱与缺陷》最后一章总结了全书的核心建议帮助开发者避免常见错误并编写更健壮的C代码。这些建议涵盖了代码风格、边界处理、防御性编程等多个关键方面是C程序员的宝贵经验总结。一、不要自我欺骗认清现实典型示例// 错误示例自我说服的皇帝新装while(c\t||c ||c\n)// 实际语法错误cgetc(f);问题分析赋值运算符优先级最低实际解析为while((c\t||c)( ||c\n))// 非法表达式但开发者可能自我说服这是正确写法。建议直面错误不要为明显错误找借口编译检查相信编译器警告不要忽略任何警告二、明确表达意图代码即文档1. 使用括号明确优先级// 模糊意图if(abc)// 实际解析为 if (a (b c))// 明确意图if((ab)c)// 使用括号明确优先级2. 常量在左的比较技巧// 传统写法易误写为赋值if(c\t)// 可能误写为 if (c \t)// 防御性写法if(\tc)// 误写为 if (\t c) 会编译报错建议主动明确用括号、格式、注释明确代码意图预防错误采用常量在左的写法预防赋值误写三、考查边界情况简单特例验证重要原则程序最容易在边界情况下出错应优先测试空输入空字符串、空数组、空文件单元素情况最大值/最小值边界示例数组处理// 考虑空数组和单元素数组voidprocess_array(int*arr,size_tn){if(n0)return;// 空数组处理if(n1){// 单元素特殊处理// ...return;}// 通用处理}建议优先测试边界从最简单特例开始设计和测试考虑极端值0、1、最大值、最小值等特殊情况四、使用不对称边界统一处理模式核心思想采用[start, end)的半开区间表示法取值范围大小 end - start空范围时 start end避免差一错误(off-by-one)示例循环处理// 传统对称边界易出错for(inti0;in-1;i)// 容易写成 i n// 不对称边界更安全for(inti0;in;i)// 明确且安全建议统一使用半开区间[start, end)模式避免复杂计算减少边界计算中的加减操作五、警惕隐藏的Bug了解语言特性1. 避免生僻特性// 晦涩写法依赖实现细节inta1;printf(%d %d %d\n,a,a,a);// 未定义行为// 明确写法inta1;intba;printf(%d %d\n,a,b);2. 注意移植性问题避免依赖特定字节序避免依赖未定义行为使用标准库而非编译器扩展建议坚持标准只使用众所周知的语言特性查阅文档不确定时查阅语言标准文档六、防御性编程假设最坏情况1. 验证输入假设// 不安全假设voidprocess(int*arr,intn){for(inti0;in;i){arr[i]i*2;// 假设arr不为NULL}}// 防御性写法voidprocess(int*arr,intn){if(arrNULL||n0)return;// 验证输入for(inti0;in;i){arr[i]i*2;}}2. 检查边界条件// 危险的内存访问voidset(int*p,intn){*pn;// 不检查p是否为NULL}// 安全版本voidset(int*p,intn){if(p!NULL)*pn;}3. 处理可能的错误FILE*filefopen(data.txt,r);if(fileNULL){// 错误处理而非继续执行perror(无法打开文件);return;}// 正常处理建议验证所有输入不信任任何外部输入检查返回值重要函数调用检查返回值准备错误处理为所有可能错误提供处理路径七、综合编程准则代码清晰性使用有意义的变量名 添加必要的注释 保持函数短小专注错误预防编译时开启所有警告 使用静态分析工具 定期进行代码审查测试策略单元测试覆盖边界情况 集成测试发现交互问题 压力测试验证稳定性持续学习阅读语言标准文档 学习常见陷阱案例 参与代码审查过程八、全书总结《C陷阱与缺陷》通过大量真实案例揭示了C编程中的常见陷阱从词法、语法、语义到连接、库函数、预处理器和可移植性等多个层面进行了深入分析。最终章的建议是全书精华的总结帮助开发者建立防御性编程思维写出更健壮可靠的C代码。第1章. 关注由C语言词法分析的方式所造成的问题。第2章. 将关注那些由对于语法的歧义理解所造成的错误。第3章. 关注语义误解在这里语义是由符号或单词如何组成更大的单元所体现的。编程者本想表达一件事却可能实际上表达成另外一件事。第4章. 关注连接问题认识到一个C程序通常被分成几部分并分别编译最后再组合在一起。这个过程被叫做连接而且是程序和环境的联系之一。第5章. 讨论库函数的误用尽管严格来说库函数不算是语言的一部分但是库函数对于任何C程序来说都是必须的。第6章. 讨论预处理器方面有用的东西指出我们所写的程序并不完全是我们所运行的程序但预处理器会事先对它处理。第7章. 讨论可移植性问题——即一个程序在一个编译器上正常运行但在另一个上运行出错。第8章. 对于保守编程提出了一些建议并给出了其他章节练习的答案。关键收获理解比记忆更重要预防比修复更有效简单比复杂更可靠