个人理解:程序第一是要供人阅读的,方便业内人员交流、沟通。也方便自己或者他人维护、升级。所以编写程序需要一定的规约,来保持编写代码的简洁性和一致性。
关于c语言基本数据类型:
为方便跨硬件平台移植,我定义一下数据类型。
typedef unsigned char BOOLEAN;
typedef unsigned char INT8U;
typedef signed char INT8S;
typedef unsigned short INT16U;
typedef signed short INT16S;
typedef unsigned int INT32U;
typedef signed int INT32S;
typedef float FP32;
typedef double FP64;
程序里统一使用以上新定义的数据类型,移植时只需重新定义即可。
关于标示符的定义:
标示符主要包括 局部变量、全局变量、函数、宏定义。分别对其进行规约。
阅读代码时首先关注标示符含义,因此所有标示符均按照逻辑意义分级法定义。对全局变量采用大小写混合方式,大写字母用于分割各个单词,例如,Msg、ErrNum、OSSemPend(取自ucos的信号量操作函数)。若中间存在大写字母缩写,可以使用下划线,例如,Read_RFC_Text.。缩写方式,简单单个词语略去元音,复杂的标示符采用各个词语的首字母或者略去元音后的单词组合。
局部变量使用小写字母表示,若比较复杂,可以使用下划线。例如,kernel_text_address
其中定义结构体类型时,标示符最后添加 “_t”,例如:Cat _t 代表一种车的数据类型。
定义函数名称时:若定义的是模块对外接口函数遵循全局变量的方式,并使用谓语加宾语的方式,例如:WriteByte。
如果函数为最底层,可以考虑用全部小写,单词间采用带下划线的形式。如底层图形函数:pixel、lineto以及读键盘函数get_key 等。且这些函数仅供模块内部使用,并不对外提供接口,因此使用static关键字限定。
宏定义:若程序中需频繁调用很小部分代码或者常量定义,可以定义成宏。标示符使用大写字母,各个单词间使用下划线分割。例如,T_LWIP_THREAD_STKSIZE(取自lwip源码)。复杂带参数的宏定义这样定义,
#define FOO(x) do { \
printf("arg is %s\n", x); \
do_something_useful(x); \
} while(0)
用do-while(0)方式定义宏,完全不用担心使用者如何使用宏,也不用给使用者加什么约束。
在头文件中使用以下代码防止重复包含。
#ifndef __DEBUG_H
#define __DEBUG_H
#endif
注意:一个工程中标示符的定义要尽量保持风格一致,尽量避免使用汉语拼音。
语句、语句块、赋值与运算符。
为了凸显if、for、do、switch等关键词,在这些关键字之后添加一个空格。在运算符前后也各添加一个空格。例如:
if (pmem == (OS_MEM *)0)
对花括号的缩进方式,{和上一行语句对齐,}和{对齐。对于深层次for循环和if采用递层缩进方式。例如:
for (i = 0;i < max_num;i++)
{
for (j = 0; j < max_num; j++)
{
语句;
}
}
较长的语句应进行分割,例如
(void)OSTaskCreateExt(OS_TaskStat,
(void *)0,
&OSTaskStatStk[OS_TASK_STAT_STK_SIZE - 1],
OS_STAT_PRIO,
OS_TASK_STAT_ID,
&OSTaskStatStk[0],
OS_TASK_STAT_STK_SIZE,
(void *)0,
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
分割成的新行应进行重新排版,使其尽量整齐。
注释:
在代码的功能、意图层次上进行注释,即注释解释代码难以直接表达的意图,而不是重复描
述代码。
对全局变量应进行详细的注释。
定义变量应一行定义一个,方便注释。
函数的注释:一般包括函数名称 、功能描述、入口参数、出口参数、使用方法。例如:
//*------------------------------------------------------------------------------------------------
//* 函数名称 : SysThreadNew
//* 功能描述 : 建立一个新线程
//* 入口参数 : <thread>[in] 新线程的入口地址
//* : <arg>[in] 传递给新线程的参数
//* :<prio>[in] 由LwIP指定的新线程优先级,这个优先级从1开始
//* 出口参数 : 返回线程优先级,注意这与prio不同。这个值实际等于T_LWIP_THREAD_START_PRIO + prio,
//* : 如果建立不成功则返回0
//* 使用方法:SysThreadNew(tcpip_thread, NULL, TCPIP_THREAD_PRIO);
//*------------------------------------------------------------------------------------------------
针对函数的注释,有两类人关心其内容,若函数是对外提供接口的,那使用者关心怎么使用这个函数,若是开发人员想更改其实现算法,则更关心其实现方案。可根据实际情况做有针对性的注释。若是对外提供接口,注释主要是针对使用者的,重点写怎么使用这个函数以及注意事项。若是内部功能函数的注释,则主要描述实现思路和策略。方便开发者理解你的实现细节。
文件注释:
*------------------------------------------------------------------------------------------------
//* 文件名 :
//* 功能描述 :
//* 作者 :
//* 版本 : 0.1
//* 建立日期、时间 :
//* 修改日期、时间 :
//* 修改原因 :
//* 修改记录:
//*------------------------------------------------------------------------------------------------
//*------------------------------------------ 头文件 ----------------------------------------------
关于工程中文件名的命名,不同系统对文件名大小写处理不同,因此统一采用小写,名字长的使用下划线分割。如:
sys_arch.c
附录1:常见单词缩写
附表2:常用反义词
add/remove begin/end create/destroy
insert/delete first/last get/release
increment/decrement put/get add/delete
lock/unlock open/close min/max
old/new start/stop next/previous
source/target show/hide send/receive
source/destination copy/paste up/down