+++++++++++++++++++++
W十一? 一个完整的例子
+++++++++++++++++++++
265.模仿软g的功能时, 要依照相似实体的U\(c|函数|模块). 在相似的现有实体?br />, 为简化对源代码库的文本查? 应选取比较|见的名
U?
266.自动生成的文件常怼在文件的开x一D|? 说明q种情况.
267.如果试图_地分析代? 一般会陷入数量众多的类|文g和模块中, q些内容会很
快将我们Ҏ; 因此, 我们必须需要理解的代码限定
在绝对必需的范围之?
268.采用一U广度优先查扄? 从多Ҏ克代码阅M存在的问? q到扑և克服?br />们的Ҏ为止
++++++++++++++
W九? pȝ构架
++++++++++++++
182.一个系l可?在重大的pȝ中也实如此)同时出多U不同的构架cd. 以不同的
方式查同一pȝ|分析pȝ的不同部分|或用不同
别的分解, 都有可能发现不同的构架类?
183.协同式的应用E序, 或者需要协同访问共享信息或资源的半自治q程, 一般会采用
集中式储存库构架.
184.黑板pȝ使用集中式的储存? 存储非结构化的键/值对, 作ؓ大量不同代码元g?br />间的通信集线?
185.当处理过E可以徏模|设计和实现成一pd的数据变换时, 常常会用数据流(或管
道—过滤器)构架.
186.在批量进行自动数据处理的环境? l常会采用数据流构架, 在对数据工具提供?br />量支持的q_上尤其如?
187.数据构架的一个明昑־兆是: E序中用时文件或水U?pipeline)在不同进
E间q行通信.
188.使用囄来徏模面向对象构架中cȝ关系.
189.可以源代码输入到徏模工具中, 逆向推导出系l的构架.
190.拥有大量同子系l的pȝ, 常常按照分层构架q行l织.
191.分层构架一般通过堆叠拥有标准化接口的软glg来实?
192.pȝ中每个层可以下面的层看作抽象实? q且(只要该层满它的需求说??br />兛_上面的层如何使用?
193.层的接口既可以是支持特定概念的互补函数族, 也可以是一pd支持同一抽象接口
不同底层实现的可互换函数.
194.用C语言实现的系l? 常常用函数指针的数组, 表达层接口的多\复用操作.
195.用面向对象的语言实现的系l? 使用虚方法调用直接表辑֯层接口的多嘴复用操作
.
196.pȝ可以使用不同的|独特的层ơ分解模型跨各种坐标轴进行组l?
197.使用E序切片技? 可以程序中的数据和控制之间依赖关系集中C?
198.在ƈ发系l中, 一个单独的pȝlg起到集中式管理器的作? 负责启动|停止和协
调其他系l进E和d的执?
199.许多现实的系l都会博采众家之? 当处理此cȝl时, 不要徒劳地寻找无所不包
的构架图; 应该不同构枉g为独立但相关的实?br />
来进行定位|识别q了?
200.状态变q图常常有助于理清状态机的动?
201.在处理大量的代码? 了解代码分解成单独单元的机制极为重?
202.大多数情况下, 模块的物理边界是单个文g|l织C个目录中的多个文件或拥有l?br />一前缀的文件的集合.
203.C中的模块, 由提供模块公开接口的头文g和提供对应实现的源文件组?
204.对象的构造函数经常用来分配与对象相关的资? q初始化对象的状? 函数一?br />用来释放对象在生命期中占用的资源.
205.对象Ҏl常使用cdD|存储控制所有方法运作的数据(比如查找表或字典)或维
护类q作的状态信?例如, 赋给每个对象一个标识符?br />
计数?.
206.在设计良好的cM, 所有的字段都应在声明ؓprivate, q用公开的访问方法提供对
它们的访?
207.在遇到friend声明? 要停下来分析一? 看看l过cd装在设计上的理由.
208.可以有节制地用运符增强特定cȝ可用? 但用q算W重? 类实现为拥有内
建算术类型相关的全部功能的类实体, 是不恰当?
209.泛型实现不是在编译期间通过宏替换或语言所支持的功?比如C++模板和Ada的泛?br />?来实? 是在运行期间通过使用数据元素的指?br />
和函数的指针|或对象的多态性实?
210.抽象数据cdl常用来装常用的数据组l方?比如树|列表或栈), 或者对用户?br />藏数据类型的实现l节.
211.使用库的目的多种多样: 重用源代码或目标代码, l织模块集合, l织和优化编?br />q程, 或是用来实现应用E序各种Ҏ的按需载入.
212.大型的|分布式的pȝl常实现多互相协作的q程.
213.对于Z文本的数据储存库, 可以通过览存储在其中的数据, 破译出它的结?
214.可以通过查询数据字典中的? 或用数据库专有的SQL命o, 比如show table, ?br />分析关系型数据库的模?
215.识别出重用的构架元素? 可以查找其最初的描述, 了解正确C用这U构架的?br />? 以及可能出现的误?
216.要详l分析徏立在某种框架之上的应用程? 行动的最佌\U就是从研究框架自n
开?
217.在阅d导生成的代码? 不要期望太高, 否则您会感到失望.
218.学习几个基本的设计模式之? 您会发现, 您查看代码构架的方式会发生改? ?br />的视野和词汇会扩展到能够识别和描述许多通用的Ş
?
219.频繁使用的一些模? 但ƈ不显式地指出它们的名U? q是׃构架性设计的重用
l常先于模式的Ş?
220.误着按照底层模式来理解构? 即代码中ƈ没有明确地提及模?
221.大多数解释器都遵循类似的处理构架, 围绕一个状态机q行构徏, 状态机的操作依
赖于解释器的当前状态|E序指o和程序状?
222.多数情况? 参考构架只是ؓ应用E序域指定一U概忉|的l构, 具体的实现ƈ?br />必须늅q种l构.
+++++++++++++++++
W十? 代码阅读工具
+++++++++++++++++
223.词汇工具可以高效地在一个大代码文g中或者跨多个文g查找某种模式.
224.使用E序~辑器和正则表达式查扑֑? 览庞大的源代码文g.
225.以只L式浏览源代码文g.
226.使用正则表达式 ^function name 可以扑և函数的定?
227.使用正则表达式的字符c? 可以查找名称遵@特定模式的变?
228.使用正则表达式的否定字符c? 可以避免非积极匹?
229.使用正则表达式 symbol-1. *symbol-2, 可以查找出现在同一行的W号.
230.使用~辑器的 tags 功能, 可以快速地扑և实体的定?
231.可以用特定的 tag 创徏工具, 增加~辑器的览功能.
232.使用~辑器的大纲视图, 可以获得源代码结构的鸟瞰?
233.使用您的~辑器来源代码中圆括号|Ҏ号和花括L匚w.
234.使用 grep 跨多个文件查找代码模?
235.使用 grep 定位W号的声明|定义和应?
236.当您不能_地表q要查找的内Ҏ, 请用关键单词的词干对程序的源代码进?br />查找.
237.用 grep qo其他工具生成的输? 分离出您要查扄?
238. grep 的输送到其他工具, 使复杂处理Q务自动化.
239.通过对 grep 的输行流~辑, 重用代码查找的结?
240.通过选取与噪x式不匚w的输(grep-v), qo虚假的 grep 输出.
241.使用 fgrep 在源代码中查扑֭W串列表.
242.查找注释, 或标识符大小写不敏感的语a~写的代码时, 要用大写不敏感的?br />式匹?grep -i).
243.使用 grep –n 命o行开? 可以创徏与给定正则表辑ּ匚w的文件和行号的检?br />?
244.可以使用 diff 比较文g或程序不同版本之间的差别.
245.在运行 diff 命o? 可以使用 diff –b, 使文件比较算法忽略结I格, 用?br />–w 忽略所有空白区域的差异, 用 –i 使文件比较对?br />
写不敏?
246.不要对创q代码阅读工具心存畏惧.
247.在构q代码阅读工具? 要充分利用现代快速原型语a所提供的能? 从简
单开? Ҏ需要逐渐改进; 使用利用代码词汇l构?br />
各种试探? 要允怸些输出噪x寂静(无关输出或缺p?; 使用其他工具对输?br />q行预处? 或者对输出q行后期处理.
248.要ɾ~译器成为您? 指定恰当U别的编译器警告, q小心地评估生成的结?
249.使用C预处理器理清那些滥用预处理器Ҏ的E序.
250.要彻底地了解~译器如何处理特定的代码? 需要查看生成的W号(汇编)代码.
251.通过分析相应目标文g中的W号, 可以清晰C解源文g的输入和输出.
252.使用源代码浏览器览大型的代码集合以及对象类?
253.要抵制住按照您的~码规范对外部代码进行美化的诱惑; 不必要的~排更改会创?br />不同的代? q妨工作的l织.
254.优美打印E序和编辑器语法着色可以得程序的源代码ؓ易读.
255.cdecl E序可以难以理解的C和C++cd声明转换成纯p(反之亦然).
256.实际q行E序, 往往可以更深d理解E序的动?
257.pȝ调用|事g和数据包跟踪E序可以增进对程序动作的理解.
258.执行剖析器可以找出需要着重优化的代码, 验证输入数据的覆盖? 以及分析法
的动?
259.通过查从未执行的代码? 可以扑և试覆盖的弱? q据此修正测试数?
260.要探I程序动态动作时的每个细? 需要在调试器中q作?
261.您觉得难以理解的代码打印到U怸.
262.可以l制囄来描l代码的动作.
263.可以试着向别Zl您在阅ȝ代码, q样做一般会增进您对代码的理?
264.理解复杂的算法或巧妙的数据结? 要选择一个安静的环境, 然后聚精会神地考虑
, 不要借助于Q何计机化或自动化的帮助.
+++++++++++++++++++
W七? ~码规范和约?br />
+++++++++++++++++++
137.了解了给定代码库所遵@的文件组l方式后, p更有效率地浏览它的源代码.
138.阅读代码? 首先要确保您的编辑器或优打印程序的tab讄, 与代码遵循的风格
规范一?
139.可以使用代码块的~进, 快速地掌握代码的Ml构.
140.对编排不一致的代码, 应该立即l予_的警?
141.分析代码? ҎCؓXXX, FIXME和TODO的代码序列要格外注意: 错误可能潜?br />在其?
142.帔R使用大写字母命名, 单词用下划线分隔.
143.在遵循Java~码规范的程序中, 包名(package name)L从一个顶U的域名开??br />? org, com), cd和接口名由大写字母开? Ҏ
和变量名由小写字母开?
144.用户界面控g名称之前的匈牙利记法的前~cd标记可以帮助我们定它的作用.
145.不同的编E规范对可移植构造的构成有不同的d.
146.在审查代码的可移植? 或以某种l定的编码规范作为指南时, 要注意了解规范对
可移植性需求的界定与限?
147.如果GUI功能都用相应的~程l构来实? 则通过代码审查可以L地验证给定用
L面的规格说明是否被正地采用.
148.了解目~译q程的组l方式与自动化方式之? 我们p够快速地阅读与理解对
应的~译规则.
149.当检查系l的发布q程? 常常可以相应发行格式的需求作为基?
++++++++++++
W八章: 文档
++++++++++++
150.阅读代码? 应该可能地利用M能够得到的文?
151.阅读一时代码所得到的信息只不过相当于阅M分钟文档.
152.使用pȝ的规D明文? 了解所阅读代码的运行环?
153.软g需求规D明是阅读和评C码的基准.
154.可以系l的设计规格说明作ؓ认知代码l构的\U图, 阅读具体代码的指?
155.试规格说明文档为我们提供可以用来对代码q行预演的数?
156.在接触一个未知系l时, 功能性的描述和用h南可以提供重要的背景信息,从而更
好地理解阅读的代码所处的上下?
157.从用户参考手册中, 我们可以快速地获取, 应用E序在外观与逻辑上的背景知识,
从管理员手册中可以得知代码的接口|文g格式和错误消
息的详细信息.
158.利用文档可以快捷地获取系l的概况, 了解提供特定Ҏ的代码.
159.文档l常能够反映和提C出pȝ的底层结?
160.文档有助于理解复杂的法和数据结?
161.法的文字描q能够不透明(晦ӆ, 难以理解)的代码变得可以理?
162.文档常常能够阐明源代码中标识W的含义.
163.文档能够提供非功能性需求背后的理论基础.
164.文档q会说明内部~程接口.
165.׃文档很少像实际的E序代码那样q行试, q受人关? 所以它常常可能存在
错误|不完整或q时.
166.文档也提供测试用? 以及实际应用的例?
167.文档常常q会包括已知的实现问题或bug.
168.环境中已知的~点一般都会记录在源代码中.
169.文档的变更能够标出那些故障点.
170.对同一D|代码重复或互相冲H的更改, 常常表示存在Ҏ性的设计~陷, 从而
得维护h员需要用一pd的修补程序来修复.
171.怼的修复应用到源代码的不同部分, 常常表示一U易犯的错误或疏? 它们同样
可能会在其他地方存在.
172.文档常常会提供不恰当的信? 误导我们Ҏ代码的理?
173.要警惕那些未归档的特? 每个实例归cMؓ合理|疏忽或有? 相应地决定是否应
该修复代码或文档.
174.有时, 文档在描q系l时, q按照已完成的实现, 而是pȝ应该的样子或来?br />实现.
175.在源代码文档? 单词gork的意思一般是指”理解?
176.如果未知的或Ҏ用法的单词阻了对代码的理解, 可以试着在文档的术语?如果
存在的话)|New Hacker’s Dictionary[Ray96]|或在
Web搜烦引擎中查扑֮?
177.L要以批判的态度来看待文? 注意非传l的来源, 比如注释|标准|出版物|试
用例|邮g列表|新闻l|修订日志|问题跟踪数据库|?br />
销材料|源代码本w?
178.L要以批判的态度来看待文? ׃文档永远不会执行, Ҏ档的试和正式复
查也很少辑ֈ对代码的同样水^, 所以文档常怼误导
读? 或者完全错?
179.对于那些有缺L代码, 我们可以从中推断出它的真实意?
180.在阅d型系l的文档? 首先要熟悉文档的Ml构和约?
181.在对付体U庞大的文档? 可以使用工具, 或将文本输出到高品质输出讑֤? ?br />如激光打印机, 来提高阅ȝ效率.
+++++++++++++++++
W六? 应对大型目
+++++++++++++++++
116.我们可以通过览目的源代码树—包含项目源代码的层ơ目录结? 来分析一?br />目的组l方? 源码树常常能够反映出目在构架和
软gq程上的l构.
117.应用E序的源代码树经常是该应用程序的部vl构的镜?
118.不要被庞大的源代码集合吓? 它们一般比型的专门项目组l得更出?
119.当您首次接触一个大型项目时, 要花一些时间来熟悉目的目录树l构.
120.目的源代码q不只是~译后可以获得可执行E序的计机语言指o; 一个项目的
源码树一般还包括规格说明|最l用户和开发h员文档|
试脚本|多媒体资源|~译工具|例子|本地化文件|修订历史|安装q程和许可信?
121.大型目的编译过E一般声明性地借助依赖关系来说? 依赖关系由工L? ?br />make及其zE序, 转换成具体的~译行动.
122.大型目? 制作文g常常由配|步骤动态地生成; 在分析制作文件之? 需要先
执行目特定的配|?
123.查大型编译过E的各个步骤? 可以使用makeE序?n开兌行预?
124.修订控制pȝ提供从储存库中获取源代码最新版本的方式.
125.可以使用相关的命? 昄可执行文件中的修订标识关键字, 从而将可执行文件与
它的源代码匹配v?
126.使用修订日志中出现的bug跟踪pȝ内的~号, 可以在bug跟踪pȝ的数据库中找?br />有关的问题的说明.
127.可以使用修订控制pȝ的版本储存库, 扑և特定的变更是如何实现?
128.定制~译工具用在软g开发过E的许多斚w, 包括配置|~译q程理|代码的生?br />|试和文档编?
129.E序的调试输出可以帮助我们理解程序控制流E和数据元素的关键部?
130.跟踪语句所在的地点一般也是算法运行的重要部分.
131.可以用断a来检验算法运作的步骤|函数接收的参数|E序的控制流E|底层g的属
性和试用例的结?
132.可以使用对算法进行检验的断言来证实您对算法运作的理解, 或将它作为推理的?br />?
133.对函数参数和l果的断al常记录了函数的前置条g和后|条?
134.我们可以测试整个函数的断言作ؓ每个l定函数的规D?
135.试用例可以部分C替函数规D?
136.可以使用试用例的输入数据对源代码序列进行预?
+++++++++++++++
W四? C数据l构
+++++++++++++++
67.Ҏ底层的抽象数据类型理解显式的数据l构操作.
68.C语言? 一般用内建的数组cd实现向量, 不再对底层实现进行抽?
69.N个元素的数组可以被序列for (i=0; i<N; i++)完全处理; 所有其他变体都应该引v
警惕.
70.表达式sizeof(x)M得到用memset或memcpy处理数组x(不是指针)所需的正字节数
.
71.区间一般用区间内的W一个元素和区间后的W一个元素来表示.
72.不对U区间中元素的数目等于高位边界与低位边界的差.
73.当不对称区间的高位边界等于低位边界时, 区间为空.
74.不对U区间中的低位边界代表区间的W一个元? 高位边界代表区间外的W一个元?br />.
75.l构的数l常常表C由记录和字D늻成的?
76.指向l构的指针常常表C问底层记录和字段的游?
77.动态分配的矩阵一般存储ؓ指向数组列的指针或指向元素指针的指针; q两U类型都
可以按照二维数组q行讉K.
78.以数lŞ式存储的动态分配矩? 用自定义讉K函数定位它们的元?
79.抽象数据cd为底层实现元素的使用(或误?方式提供一U信心的量度.
80.数组用从0开始的序整数为键, l织查找?
81.数组l常用来Ҏ制结构进行高效编? 化程序的逻辑.
82.通过在数l中每个位置存储一个数据元素和一个函数指?指向处理数据元素的函?br />), 可以代码与数据兌h.
83.数组可以通过存储供程序内的抽象机(abstract machine)或虚拟机(virtual machin
e)使用的数据或代码, 控制E序的运?
84.可以表辑ּsizeof(x) / sizeof(x[0])理解为数lx中元素的个数.
85.如果l构中含有指向结构自w|名ؓnext的元? 一般说? 该结构定义的是单向链
表的l点.
86.指向链表l点的持久?如全局|静态或在堆上分?指针常常表示链表的头?
87.包含指向自n的next和prev指针的结构可能是双向链表的结?
88.理解复杂数据l构的指针操作可以将数据元素MؓҎ|指针Mؓ头.
89.递归数据l构l常用递归法来处?
90.重要的数据结构操作算法一般用函数参数或模板参数来参数?
91.囄l点常常序地存储在数组? 链接到链表中, 或通过囄辚w接v?
92.图中的边一般不是隐式地通过指针, 是昑ּC为独立的l构来表C?
93.囄边经常存储ؓ动态分配的数组或链? 在这两种情况? 辚w锚定在图的结点上
.
94.在无向图? 表达数据时应该将所有的l点看作是等同的, cM? q行处理d?br />代码也不应该Z它们的方向来区分?
95.在非q通图? 执行遍历代码应该能够接通孤立的子图.
96.处理包含回\的图? 遍历代码应该避免在处理图的回路进入@?
97.复杂的图l构? 可能隐藏着其他cd的独立结?
+++++++++++++++++
W五? 高控制程
+++++++++++++++++
98.采用递归定义的算法和数据l构l常用递归的函数定义来实现.
99.推理递归函数? 要从基准落伍试开? q认证每ơ递归调用如何逐渐接近非递归
基准范例代码.
100.单的语言常常使用一pd遵@该语a语法l构的函数进行语法分?
101.推理互递归函数? 要基于底层概늚递归定义.
102.N归调用{同于一个回到函数开始处的@?
103.throws子句从方法的定义中移? 然后q行Java~译器对cȝ源代码进行编?
可以容易地扑ֈ那些可能隐式地生成异常的Ҏ.
104.在多处理器计机上运行的代码常常围绕q程或线E进行组l?
105.工作ƈ行模型用于在多个处理器间分配工作, 或者创Z个Q务池, 然后大?br />需要处理标准化的工作进行分?
106.ZU程的管理?工hq行模型一般将耗时的或d的操作分配给工h子Q? ?br />而维护中心Q务的响应?
107.Zq程的管理?工hq行模型一般用来重用现有的E序, 或用定义良好的接口组
l和分离_粒度的pȝ模块.
108.Z水U的q行处理? 每个d都接收到一些输? 对它们进行一些处? q?br />生成的输出传递给下一个Q? q行不同的处?
109.竞争条g很难捉摸, 相关的代码常怼竞争条件扩散到多个函数或模? 因?
很难隔离׃竞争条gD的问?
110.对于出现在信号处理器中的数据l构操作代码和库调用要保持高度警?
111.在阅d含宏的代码时, 要注? 宏既非函? 也非语句.
112.do…while(0)块中的宏{同于控制块中的语句.
113.宏可以访问在它的使用点可见的所有局部变?
114.宏调用可改变参数的?br />
115.Z宏的标记拼接能够创徏新的标记W?
+++++++++++++++++++
W三? 高C数据cd
+++++++++++++++++++
52.了解特定语言构造所服务的功能之? p够更好地理解使用它们的代?
53.识别q归cM用指针的理由.
54.在CE序? 指针一般用来构造链式数据结构|动态分配的数据l构|实现引用调用|?br />问和q代数据元素|传递数l参数|引用函数|作ؓ其他
值的别名|代表字符串|以及直接讉Kpȝ内存.
55.以引用传递的参数可以用来q回函数的结? 或者避免参数复制带来的开销.
56.指向数组元素地址的指? 可以讉K位于特定索引位置的元?
57.指向数组元素的指针和相应的数l烦? 作用在二者上的运具有相同的语义.
58.使用全局或static局部变量的函数大多数情况都不可重入(reentrant).
59.字符指针不同于字W数l?
60.识别和归cd用结构或q体的每种理由.
61.C语言中的l构多个数据元素集合在一? 使得它们可以作ؓ一个整体来使用, ?br />来从函数中返回多个数据元素|构造链式数据结构|映射
数据在硬件设备||络链接和存储介质上的组l方式|实现抽象数据cd|以及以面向对?br />的方式编E?
62.q体在CE序中主要用于优化存储空间的利用|实现多态|以及讉K数据不同的内?br />表达方式.
63.一个指? 在初始化为指向N个元素的存储I间之后, 可以作为N个元素的数组来
?
64.动态分配的内在块可以电焊工地释? 或在E序l束旉? 或由垃圾回收器来完成
回收; 在栈上分配的内存块当分配它的函数退出后释放
.
65.CE序使用typedef声明促进抽象, q增Z码的易读? 从而防范可UL性问? q?br />模拟C++和Java的类声明行ؓ.
66.可以typedef声明理解成变量定? 变量的名U就是类型的名称; 变量的类型就?br />与该名称对应的类?
++++++++++++++++++++
W二? 基本~程元素
++++++++++++++++++++
19.W一ơ分析一个程序时, main是一个好的v始点.
20.层叠if-else if-...-else序列可以看作是由互斥选择组成的选择l构.
21.有时, 要想了解E序在某一斚w的功? q行它可能比阅读源代码更为恰?
22.在分析重要的E序? 最好首先识别出重要的组成部?
23.了解局部的命名U定, 利用它们来猜变量和函数的功能用?
24.当基于猜修改代码时, 您应该设计能够验证最初假讄q程. q个q程可能包括?br />~译器进行检查|引入断言|或者执行适当的测试用?
25.理解了代码的某一部分, 可能帮助你理解余下的代码.
26.解决困难的代码要从容易的部分入手.
27.要养成遇到库元素去阅读相关文档的习? q将会增强您阅读和编写代码的能力.
28.代码阅读有许多可选择的策? 自底向上和自向下的分析|应用试探法和查注?br />和外部文? 应该依据问题的需要尝试所有这些方?
29.for (i=0; i<n; i++)形式的@环执行n? 其他M形式都要心.
30.涉及两项不等试(其中一包括相{条?的比较表辑ּ可以看作是区间成员测?
31.我们l常可以表辑ּ应用在样本数据上, 借以了解它的含义.
32.使用De Morgan法则化复杂的逻辑表达?
33.在阅读逻辑乘表辑ּ? 问题可以认ؓ正在分析的表辑ּ以左的表辑ּ均ؓtrue; ?br />阅读逻辑和表辑ּ? cM? 可以认ؓ正在分析的表
辑ּ以左的表辑ּ均ؓfalse.
34.重新l织您控制的代码, 使之更ؓ易读.
35.用条件运行符? :的表辑ּ理解为if代码.
36.不需要ؓ了效? 牺牲代码的易L?
37.高效的算法和Ҏ的优化确实有可能使得代码更ؓ复杂, 从而更隄? 但这q不?br />味着使代码更为紧凑和不易M提高它的效率.
38.创造性的代码布局可以用来提高代码的易L?
39.我们可以使用I格|临时变量和括h高表辑ּ的易L?
40.在阅L所控制的代码时, 要养成添加注释的习惯.
41.我们可以用好的羃q以及对变量名称的明智选择, 提高~写Ơ佳的程序的易读?
42.用diffE序分析E序的修订历史时, 如果q段历史跨越了整体重新羃? 常常可以?br />q指?w选项, 让diff忽略I白差异, 避免׃更改?br />
~进层次而引入的噪音.
43.do循环的@环体臛_执行一?
44.执行术q算? 当b=2n-1? 可以a&b理解为a%(b+1).
45.a<<n理解为a*k, k=2n.
46.a>>n理解为a/k, k=2n.
47.每次只分析一个控制结? 它的内容看作是一个黑?
48.每个控制结构的控制表达式看作是它所包含代码的断a.
49.return, goto, break和continue语句, q有异常, 都会影响l构化的执行程. ?br />于这些语句一般都会终止或重新开始正在进行的循环,
因此要单独推理它们的行ؓ.
50.用复杂@环的变式和不变式, 对@环进行推?
51.使用保持含义不变的变换重新安排代? 化代码的推理工作.