一个变量只用来表示一个特定功能,不能把一个变量作多种用途,即同一变量取值不同时,其代表的意义也不同。
示例:具有两种功能的反例
WORD DelRelTimeQue(void)
{
WORD Locate;
Locate = 3;
Locate = DeleteFromQue(Locate); /* Locate具有两种功能:位置和函数DeleteFromQue的返
回值 */
return Locate;
}
正确做法:使用两个变量
WORD DelRelTimeQue(void)
{
WORD Ret;
WORD Locate;
Locate = 3;
Ret = DeleteFromQue(Locate);
return wValue;
}
相关的一组信息才是构成一个结构体的基础,结构的定义应该可以明确的描述一个对象,而不是一组相关性不强的数据的集合。 设计结构时应力争使结构代表一种现实事务的抽象,而不是同时代表多种。结构中的各元素应代表同一事务的不同侧面,而不应把描述没有关系或关系很弱的不同事务的元素放到同一结构中。 示例:如下结构不太清晰、合理。
typedef struct STUDENT_STRU
{
unsigned char name[32]; /* student's name */
unsigned char age; /* student's age */
unsigned char sex; /* student's sex, as follows */
/* 0 - FEMALE; 1 - MALE */
unsigned char teacher_name[32]; /* the student teacher's name */
unsigned char teacher_sex; /* his teacher sex */
} STUDENT;
若改为如下,会更合理些。
typedef struct TEACHER_STRU
{
unsigned char name[32]; /* teacher name */
unsigned char sex; /* teacher sex, as follows */
/* 0 - FEMALE; 1 - MALE */
unsigned int teacher_ind; /* teacher index */
} TEACHER;
typedef struct STUDENT_STRU
{
unsigned char name[32]; /* student's name */
unsigned char age; /* student's age */
unsigned char sex; /* student's sex, as follows */
/* 0 - FEMALE; 1 - MALE */
unsigned int teacher_ind; /* his teacher index */
} STUDENT;
单个文件内部可以使用 static 的全局变量,可以将其理解为类的私有成员变量。
全局变量应该是模块的私有数据,不能作用对外的接口使用,使用 static 类型定义,可以有效防止外部文件的非正常访问,建议定义一个 STATIC 宏,在调试阶段,将 STATIC 定义为 static,版本发布时,改为空,以便于后续的打补丁等操作。
#ifdef _DEBUG
#define STATIC static
#else
#define STATIC
#endif
直接使用其他模块的私有数据,将使模块间的关系逐渐走向“剪不断理还乱”的耦合状态,这种情形是不允许的。
尽管局部变量和全局变量的作用域不同而不会发生语法错误,但容易使人误解。
通讯报文中,字节序是一个重要的问题,我司设备使用的 cpu 类型复杂多样,大小端、32 位/64 位的处理器也都有,如果结构会在报文交互过程中使用,必须考虑字节序问题。
由于位域在不同字节序下,表现看起来差别更大,所以更需要注意。
对于这种跨平台的交互,数据成员发送前,都应该进行主机序到网络序的转换;接收时,也必须进行网络序到主机序的转换。
坚持建议 4.3(在首次使用前初始化变量,初始化的地方离使用的地方越近越好。)可以有效避免未初始化错误。
降低全局变量耦合度。
避免直接暴露内部数据给外部模型使用,是防止模块间耦合最简单有效的方法。
定义的接口应该有比较明确的意义,比如一个风扇管理功能模块,有自动和手动工作模式,那么设置、查询工作模块就可以定义接口为 SetFanWorkMode,GetFanWorkMode;查询转速就可以定义为 GetFanSpeed;风扇支持节能功能开关,可以定义 EnabletFanSavePower 等等。
未初始化变量是 C 和 C++程序中错误的常见来源。在变量首次使用前确保正确初始化。在较好的方案中,变量的定义和初始化要做到亲密无间。 示例:
//不可取的初始化:无意义的初始化
int speedup_factor = 0;
if (condition)
{
speedup_factor = 2;
}
else
{
speedup_factor = -1;
}
//不可取的初始化:初始化和声明分离
int speedup_factor;
if (condition)
{
speedup_factor = 2;
}
else
{
speedup_factor = -1;
}
//较好的初始化:使用默认有意义的初始化
int speedup_factor = -1;
if (condition)
{
speedup_factor = 2;
}
//较好的初始化使用?:减少数据流和控制流的混合
int speedup_factor = condition?2:-1;
//较好的初始化:使用函数代替复杂的计算流
int speedup_factor = ComputeSpeedupFactor();
系统启动阶段,使用全局变量前,要考虑到该全局变量在什么时候初始化,使用全局变量和初始化全局变量,两者之间的时序关系,谁先谁后,一定要分析清楚,不然后果往往是低级而又灾难性的。
当进行数据类型强制转换时,其数据的意义、转换后的取值等都有可能发生变化,而这些细节 若考虑不周,就很有可能留下隐患。
示例:如下赋值,多数编译器不产生告警,但值的含义还是稍有变化。
char ch;
unsigned short int exam;
ch = -1;
exam = ch; // 编译器不产生告警,此时exam为0xFFFF。