基本数据类型(P291)
1.数值概论(P292)
- 避免使用“神秘数值”
- 如果需要,可以使用硬编码的0和1
- 预防除零错误
- 使类型转换变得明显
- 避免混合类型的比较
- 注意编译器的警告
2.整数(P293)
- 检查整数除法
- 检查整数溢出
- 检查中间结果溢出
3.浮点数(P295)
使用浮点数字时主要考虑的是,很多十进制小数不能够精确地用数字计算机中的1和0来表示。比如1/3或者1/7这样的无限循环小数通常只用7位或者15位精度有效数字表示。
- 避免数量级相差巨大的数之间的加减运算
- 避免等量判断
应该找一种代替浮点数字执行等量判断的方案 - 处理舍入误差问题
- 检查语言和函数库对特定数据类型的支持
4.字符和字符串(P297)
- 避免使用神秘字符和神秘字符串
- 避免off-by-one错误
即读写操作超出了字符串末尾而导致的错误 - 了解你的语言和开发环境是如何支持Unicode的
- 在程序生命期中尽早决定国际化/本地化策略
- 如果你知道只需要支持一种文字的语言,请考虑使用ISO 8859字符集
- 如果你需要支持多种语言,请使用Unicode
- 采用某种一致的字符串类型转换策略
5.布尔变量(P301)
- 用布尔变量对程序加以文档说明
//目的不明确的布尔判断 if( ( elementIndex < 0) || ( MAX_ELEMENTS < elementIndex) || ( elementIndex == lastElementIndex) ){ ... } //目的明确的布尔判断 finished = ( elementIndex < 0) || ( MAX_ELEMENTS < elementIndex)); repeatedEntry = elementIndex == lastElementIndex; if( finished || repeatedEntry){ ... }
- 用布尔变量来简化复杂的判断(同上例子)
- 如果需要的话,创建你自己的布尔类型
6.枚举类型(P303)
- 用枚举类型来提高可读性
- 用枚举类型来提高可靠性
- 用枚举类型来简化修改
- 将枚举类型作为布尔变量的替换方案
- 检查非法数值
- 定义出枚举的第一项和最后一项,以便用于循环边界
- 把枚举类型的第一个元素留作非法值
Public Enum Country Country_InvalidFirst = 0 Country_First = 1 Country_China = 1 Country_England = 2 Country_France = 3 Country_Germany = 4 Country_India = 5 Country_Japan = 6 Country_Usa = 7 Country_Last = 7 End Enum
- 明确定义项目编写标准中第一个和最后一个元素的使用规则,并且在使用时保持一致
- 警惕给枚举元素明确赋值而带来的失误
- 如果你的语言里没有枚举类型,那么可以用全局变量或者类来模拟它
7.具名常量(P307)
具名变量很像变量,一旦赋值以后就不能再改了。具名变量允许你用一个名字而不是数字——比如说MAXIMUM_EMPLOYEES而不是1000——来表示固定的量,比如员工人数的最大值。
- 在数据声明中使用具名常量
- 避免使用文字量,即使是“安全”的
- 用具有适当作用域的变量或类来模拟具名常量
- 统一地使用具名常量
8.数组(P310)
数组是最简单和最常用的结构化数据类型。在有些语言里,数组是唯一的结构化数据类型。
- 确认所有的数组下标都没有超出数组的边界
- 考虑用容器来取代数组,或者将数组作为顺序化结构来处理
- 检查数组的边界点
- 如果数组是多维的,确认下标的使用顺序是正确的
- 提防下标串话
- 在C中结合ARRAY_LENGTH()宏来使用数组
9.创建你自己的类型(类型别名)(P311)
程序员自定义的数据类型是语言所能赋予你的一种最强有力的、最有助于澄清你对程序的理解的功能之一。1)创建自定义数据类型的指导原则
- 给所创建的类型取功能导向的名字
- 避免使用预定义类型
- 不要重定义一个预定义的类型
- 定义替代类型以便于移植
- 考虑创建一个类而不是使用typedef
不常见的数据类型(P319)
1.结构体(P319)
- 用结构体来明确数据关系
- 用结构体简化对数据块的操作
- 用结构体来简化参数列表
- 用结构体来减少维护
2.指针(P323)
指针的使用是现代编程中最容易出错的领域之一,很多常见的安全问题,特别是缓冲区溢出,其产生都可以追溯到错误地运用指针上去。
3.全局数据(P335)
全局数据可以在程序中任意一个位置访问。大多数有经验的程序员已经得出结论:使用全局数据的风险比使用局部数据大。极富经验的程序员还认为通过一些子程序来访问数据很有帮助。1)与全局数据有关的常见问题
- 无意间修改了全局数据
- 与全局数据有关的奇异的和令人激动的别名问题
比如按引用传参- 与全局数据有关的代码重入问题
- 全局阻碍代码重用
- 与全局数据有关的非确定的初始化顺序事宜
- 全局数据破坏了模块化和智力上的可管理性
2)使用全局数据的理由
- 保存全局数值
- 模拟具名常量
- 模拟枚举类型
- 简化对极常使用的数据的使用
- 消除流浪数据
3)只有万不得已时才使用全局数据
- 首先把每一个变量设置为局部的,仅当需要时才把变量设置为全局的
- 区分全局变量和类变量
- 使用访问器子程序
4)用访问器子程序来取代全局数据
你用全局数据能做的任何事情,都可以用访问器子程序做得更好。使用访问器子程序是实现抽象数据类型和信息隐藏的一种核心方法。即使你不希望使用装备齐全的抽象数据类型,你仍然可以用访问器子程序来集中控制你的数据,并保护你免受变化的困扰。a.访问器子程序的优势
- 获得了对数据的集中控制
- 可以确保对变量的所有引用都得到了保护
- 可以自动获得信息隐藏的普遍益处
- 访问器子程序可以很容易地转变为抽象数据类型
b.如何使用访问器子程序
- 要求所有的代码通过访问器子程序来存储数据
一个好习惯是要求所有的全局数据都冠以g_前缀,并且除了该变量的访问器子程序以外,所有的代码都不可以访问具有g_前缀的变量。- 不要把你所有的全局数据都扔在一处
否则会丧失信息隐藏和抽象数据类型所带来的好处- 用锁定来控制对全局变量的访问
- 在你的访问器子程序里构建一个抽象层
- 使得对一项数据的所有访问都发生在同一个抽象层上
5)如何降低使用全局数据的风险
- 创建一种命名规则来突出全局变量
- 为全部的全局变量创建一份注释良好的清单
- 不要用全局变量来存放中间结果
- 不要把所有的数据都放在一个大对象中并到处传递,以说明你没有使用全局变量