强制类型转换的应用
C语言中void* 可以转换为任意指针
size_t 到 unsigned
变量初始化
- 从未对变量赋值。它的值只是程序启动时变量所处内存区域的值
- 变量值已经过期。变量在某个地方曾经被赋值,但该值已经不再有效
- 变量的一部分被赋值,而另一部分没有
在声明变量的时候初始化
理想情况下,在靠近第一次使用变量的位置声明和定义该变量
- 在有可能的情况下使用
const
, 定义常量,入参。 - 特别注意计数器和累加器,在下一次使用时忘记重置其值。
- 在类的构造函数中,初始化该类的数据成员
- 检查是否需要重新初始化
1 | int index = 0; |
1 | for(int i = 0; i < 10; ++i) |
尽可能缩短变量存活时间
短的变量存活时间减少了初始化错误的可能。
变量存活时间短还会使代码具有可读性。阅读者同一时间内需要阅读的代码越少,越容易理解代码。
当需要把一个大的函数,拆分成几个小程序,短的存活时间方便拆分。
在循环开始之前再去初始化该循环里使用的变量,而不是在该循环所属的子程序的开始处初始化这些变量。
直到变量即将被使用时再为其赋值。
把相关语句放在一起。把相关语句提取成单独的子程序。
开始时采用最严格的可见性,然后根据扩展变量的作用域。比如,把一个循环内的变量挪到循环外的难度要比反过来难度低,或把一个private
转变为public
的难度远比反过来难度低。
避免采用硬编码,宏定义总是好于硬编码。
TITLE_BAR_COLOR
比0xFFFFFF
更能反应出所代表的信息- 同时,也方便修改宏定义时,同时改变所有的颜色的RGB值
为变量指定单一用途
1 | temp = Sqrt(b*b - 4*a*c); |
1 | discriminant = Sqrt(b*b - 4*a*c); |
避免让代码具有隐含含义,把同一变量用于多个多个用途的另外一种方式是当变量代表不同事务时让其具有不同的取值集合。
- 变量
count
的取值可能表示某个计数,除非他等于-1
,在这种情况下表明有错误发生 - 变量
customerId
可能代表某个客户账号,除非他的取值大于50000,在这种情况下,你通过减去50000来得到过期账号。 - 变量
bytesWritten
可能表示写入输出文件的字节数,除非它的取值为负,在这种情况下他表示的是用于输出磁盘驱动器的号码。
变量名的注意事项
糟糕的变量名
1 | x = x - xx; |
良好的变量名
1 | balance = balance - lastPayment; |
为变量命名时最重要的考虑事项时,改名字要完全、准确地描述该变量所代表的事物
不包含晦涩的缩写,同时也没有歧义。
对于一个表示中国奥林匹克代表团成员数量的变量,你可能会使用NumberOfPeopleOnTheChineseOlympicTeam
表示当前利率的变量最好为rate
而不是r
.
变量名太长: numberOfPeopleOnTheChineseOlympicTeam
,numberOfSeatsInTheStadium
, maximumNumberOfPointsInModernOlympics
变量名太短: n
, np
, ntm
, ms
, nsisd
, m
, max
, min
变量名正好: numTeamMembers
, teamMemberCount
, numSeatsInStadium
, seatCount
, teamPointsMax
, pointSRecord
很多程序有表示计算机结果的变量:总额、平均值、最大值,等等。如果你要用类似于Total
、Sum
、Average
、Max
、Min
、Record
这样的限定词,那么请一定记住把限定词加到名字最后。
变量名中最重要的部分应该被放置在最前面,限定词在最后。
这样做会避免,totalRevenue
和revenueTotal
异议词语
为状态变量起一个比flag
更好的名字。最好把标记flag
看作状态变量,标记的名字中不应该含有flag
,因为你从中丝毫看不出该标记是做什么的。
含义模糊的标记
1 | if (flag) ... |
更好的状态变量命名
1 | if (dataReady) ... |
为布尔变量命名
done
用done
表示某件事情已经发生之前把变量值设为false
, 在错误已经发生时把它设为true
error
用error
表示有错误发生。在错误发生之前把变量值设为false
, 在错误已经发生时把它设为true
found
用found
来表明某个值已经找到了。在没有找到设为false
, 找到后设为true
.success
和ok
, 操作失败时设为false
, 操作成功后设为true
给布尔变量赋予隐含“真、假”含义的名字: status
和sourceFile
是很糟糕的布尔变量名。
应该把status
替换为类似error
或者statusOK
这样的名称,把sourceFile
替换为sourceFileAvailable
、sourceFileFound
使用肯定的布尔变量名,否定的布尔名如notFound
、notDone
以及notSuccessful
比较难阅读。使用肯定的语义避免双重否定带来的阅读难度。
1 | AnsiString strTmp; |
缩写的一般指导原则:
- 使用标准的缩写(列在字典中的那些常见缩写)
- 去掉虚词
and
,or
,the
等 - 去掉无用的后缀
ing
,end
- 确保不要改变变量的含义
- 反复使用上述技术,知道你把每个变量名的长度缩减到了8到20个字符,或者达到你所用的编程语言对变量名的限制字符数。
不要用每个单词中删除一个字符的方式来缩写
键入一个字符算不上是什么额外工作,而节省一个字符带来的便利却很难抵消由此而造成的可读性的损失。
缩写要一致
应该一直使用相同的缩写。要么全用Num
,要么全用No
,也不要有些地方使用全写Number
, 同时在其他地方使用缩写Num
创建你能读出来的名字
使用xPos
而不是xPstn
, 用needsCompu
而不用ndsCmptg
。这里可以使用电话沟通,如果你无法向他人读出你的代码,就请重新给变量起一个更清晰的名字。
名字对于代码的读者的意义要比对作者更重要
避免使用令人误解的名字或缩写
要确保名字的含义是明确的
避免使用具有相似含义的名字
如果你能够交换两个变量的名字而不会妨碍对程序的理解,那么你就需要为这两个变量重新命名了。
避免在名字中使用数字
如果名字中的数字真的非常重要,就请使用数组来代替一组单个的变量。如果数组不合适,那么数字就更不合适。
避免在名字中拼错单词
避免在名字中使用容易混淆的字符
- 数字
1
和小写的l
- 数字
1
和大写的L
- 数字
0
和大写的O
- 数字
2
和小写的z
- 数字
6
和大写的G
避免浮点数的数量级相差巨大的数字之间的四则运算
1 |
|
避免浮点数的等量比较
1 |
|
1 | int a = 0; |
为空语句创建一个DoNothing()预处理宏或者内联函数
1 | while(recordArray.Read(index++) != recordArray.EmptyRecord()) |