C语言编程规范(三)

7.常量、变量和结构

规则 7-1 尽量使用含义直观的常量来表示那些将在程序中多次出现的数字或字符串。

规则 7-2 需要对外公开的常量放在头文件中,不需要对外公开的常量放在定义文件的头部。

规则 7-3 去掉没必要的公共变量。
说明:公共变量是增大模块间耦合的原因之一,故应减少没必要的公共变量以降低模块间的耦合度。

规则 7-4 严禁使用未经初始化的变量作为右值。
说明:特别是在C中引用未经赋值的指针,经常会引起系统崩溃。

规则 7-5 结构的功能要单一,是针对一种事务的抽象。
说明:设计结构时应力争使结构代表一种现实事务的抽象,而不是同时代表多种。结构中的各元素应代表同一事务的不同侧面,而不应把描述没有关系或关系很弱的不同事务的元素放到同一结构中。

规则 7-6 不要设计面面俱到、非常灵活的数据结构。
示例:如下结构不太清晰、合理。

typedef struct STUDENT_STRU
{
unsigned char name[8]; /* student's name */
unsigned char age; /* student's age */
unsigned char sex; /* student's sex, as follows */
/* 0 - FEMALE; 1 - MALE */
unsigned charteacher_name[8]; /* the student teacher's name */
unisgned charteacher_sex; /* his teacher sex */
} STUDENT;

若改为如下,可能更合理些。

typedef struct TEACHER_STRU
{
unsigned char name[8]; /* teacher name */
unisgned char sex; /* teacher sex, as follows */
/* 0 - FEMALE; 1 - MALE */
} TEACHER;

typedef struct STUDENT_STRU
{
unsigned char name[8]; /* 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;

规则 7-7 结构中元素的个数应适中。若结构中元素个数过多可考虑依据某种原则把元素组成不同的子结构,以减少原结构中元素的个数。

规则 7-8 对编译系统默认的数据类型转换,也要有充分的认识。

规则 7-9 有符号和无符号之间,整型和浮点类型之间,从宽类型向窄类型,函数参数,函数的返回表达式,复杂表达式没有隐式转换。

规则 7-10 整型复杂表达式的值只能强制转换到更窄的类型且与表达式的基本类型具有相同的符号。
如果强制转换要用在任何复杂表达式上,可以应用的转换的类型应该严格限制。举例如下:

(uint32_t) (u16a + u16b) 		/* not compliant */
(uint32_t) u16a + u16b 		/* compliant */
(uint32_t) u16a + (uint32_t) u16b /* compliant */

规则 7-11 当声明用于分布式环境或不同CPU间通信环境的数据结构时,必须考虑机器的字节顺序、使用的位域及字节对齐等问题。

8.宏设计

规则 8-1 C的宏只能扩展为用大括号括起来的初始化、常量、小括号括起来的表达式、类型限定符、存储类标识符或do-while-zero 结构。

这些是宏当中所有可允许使用的形式。存储类标识符和类型限定符包括诸如extern、static和const 这样的关键字。使用任何其他形式的#define 都可能导致非预期的行为,或者是非常难懂的代码。

特别的,宏不能用于定义语句或部分语句,除了 do-while 结构。宏也不能重定义语言的语法。宏的替换列表中的所有括号,不管哪种形式的 ()、{}、[] 都应该成对出现。do-while-zero 结构(见下面的例子)是在宏语句体中唯一可接受的具有完整语句的形式。do-while-zero 结构用于封装语句序列并确保其是正确的。注意:在宏语句体的末尾必须省略分号。
例如:

/* The following are compliant */
#define PI 3.14159F /* Constant */
#define XSTAL 10000000 /* Constant */
#define CLOCK (XSTAL / 16) /* Constant expression */
#define PLUS2(X) ( (X) + 2 ) /* Macro expanding to expression */
#define STOR extern /* storage class specifier */
#define INIT(value) { (value), 0, 0 } /* braced initialiser */
#define READ_TIME_32 () \
do { \
DISABLE_INTERRUPTS (); \
time_now = (uint32_t) TIMER_HI << 16; \
time_now = time_now | (uint32_t) TIMER_LO; \
ENABLE_INTERRUPTS (); \
} while (0)	 /* example of do-while-zero */

规则 8-2 函数宏的调用不能缺少参数。
这是一个约束错误,但是预处理器知道并忽略此问题。函数宏中的每个参数的组成必须至少有一个预处理标记,否则其行为是未定义的。

规则 8-3 在定义函数宏时,每个参数实例都应该以小括号括起来。
函数宏的定义中,参数应该用小括号括起来。例如一个abs 函数可以定义成:
#define abs (x) ( ( (x) >= 0 ) ? (x) : -(x) )
不能定义成:
#define abs (x) ( ( (x) >= 0 ) ? x : -x )

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yasin墨染锦年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值