良好的编程风格(一)

本文摘自我整理编写的<嵌入式C进阶之道>,完全版本请访问http://wenku.baidu.com/view/36c515ec102de2bd960588f5.html

 

  编程的总则: 编程首要是要考虑程序的可行性,然后是可读性、可移植性、健壮性以及可测试性。大多数程序员只是关注程序的可行性,而忽略了可读性,可移植性和健壮性,其实我个人认为,程序的可行性和健壮性与程序的可读性有很大的关系,能写出可读性很好的程序的程序员,他写的程序的可行性和健壮性必然不会差,也会有不错的可移植性.程序的可读性需要程序员有一个良好的编程风格.

好风格应该成为一种习惯。如果你在开始写代码时就关心风格问题,如果你花时间去审视和改进它,你将会逐渐养成一种好的编程习惯。一旦这种习惯变成自动的东西,你的潜意识就会帮你照料许多细节问题,甚至你在工作压力下写出的代码也会更好。

 

1.排版

a. 代码缩进空格数为4个。若是可能,尽量用空格来代替Tab键,因为有些编译器不支持Tab键(我自己至今未见过,但确实有这个风险),这给程序的移植带来了问题。在keil中这个问题很容易解决,只需在在keil主界面的菜单栏点击EditConfiguration,弹出Configuration窗口,点击Editor标签,在其中C/C++ File:、ASMOther Files栏下,选中Insert spaces for tab:复选框,Tab对应的框中填4,这样按tab键就相当于按下四个空格键。

BOOL BufClr(UINT8 * dest,UINT32 size)
{
    if(NULL ==dest || NULL==size)
    {
        return FALSE;
    }
}

b. 较长的语句要分2行来书写,并用‘\’符号隔开。

uncrc=calcCRC16(Packet.p,unlen);
if((UINT8) uncrc != Packet.down_ser.mCrc[0] \
                 ||(UINT8)(uncrc>>8)!= Packet.down_ser.mCrc[1])
{
    BELL(ON);
}

c. 函数代码的参数过长,分多行来书写。

void UARTSendAndRecv(UINT8 *ucSendBuf,
        UINT8 ucSendLength,
        UINT8 *ucRecvBuf,
        UINT8 ucRecvLength)
{
    …
}

d. ifdowhileswitchforcasedefault等关键字,必须加上大括号{}

if(bSendEnd)
{
    BELL(ON);
}
else
{
    BELL(OFF);
}

//--------------------------
for(i=0; i< ucRecvLength; i++)
{
    ucRecvBuf[i]=i;
}

//--------------------------
switch(ucintStatus)
{
    case USB_INT_EP2_OUT:
    {
        USBCiEP2Send(USBMainBuf,ucrecvLen);
        USBCiEP1Send(USBMainBuf,ucrecvLen);
    }
    break;
    case USB_INT_EP2_IN:
    {
        USBCiWriteSingleCmd (CMD_UNLOCK_USB);
    }
    break;
    …
}

2.注释

a. 边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。不再有用的注释要删除。

   注释应当准确、易懂,防止注释有二义性。错误的注释不但无益反而有害。

   尽量避免在注释中使用缩写,特别是不常用缩写。

   注释的位置应与被描述的代码相邻,可以放在代码的上方或右方,不可放在下方。

 

b. 说明性文件必选在文件头着重说明,例如*.c*.h文件

/***************************************************************************
*                      定时器+计数器测频
*
* 文    件: frequency.c
* 作    者: 小瓶盖 
* 说    明:定时器+计数机测频率  
* 编写时间: 2010.3.17
* 版    本:1.0
* 修改日期: 无
*---------------------------------------------------------------------------
* 注: 本程序定义6个数码管,经过实测,在200HZ~50KHZ时结果较准确,误差小于0.4%,
*       50KHZ以上频率未进行测量.据资料表明,可以测量到120KHZ,本程序未证明.
*****************************************************************************/
#include 
void func(void)
{
}

c. 函数头应该进行注释,例如函数名称、输入参数、返回值、功能说明。

/**************将所有参数写入AT24C64,共4字节*********************
*说明:将表号和用户电量共四字节数据写入AT24C64中
*入口参数:
*    1.数据间接寻址地址-buf
*    2.写入到AT24C64的地址字-addh,addrl
*    3.写入字节数-count
*出口参数:1表示写成功,0表示写失败
***************************************************************/
bit write_byte( unsigned char * buf,      
                unsigned char addrh,
                unsigned char addrl,
                unsigned char count)
{
    ……
}

d. 全局变量要注释其功能,若为关键的局部变量同样需要注释其功能。

volatile UINT8 __ucSysMsg=SYS_IDLE;
void SYSSetMsgPriority(void)
{
    SYSMSG Msgt;//临时存储消息
    UINT8 i;
}

e. 复杂的宏定义同样要加上注释。

/* SYS_MSG_MAP 建立一个消息映射
   宏参数NAME:消息映射表的名字
   宏参数NUM_OF_MSG:消息映射的个数
*/
#define SYS_MSG_MAP(NAME,NUM_OF_MSG) do/
{  /
    DEFINE_MSG_NAME((NAME));/
    UINT8 i;/
    for(i=0;i< NUM_OF_MSG;i++)/
    {/
        ININ_CUR_MSG(i)/
    }/
}while(0)

f. 复杂的结构体同样要加上注释。

/* 奇偶校验结构体*/
typedef struct _ PKT_PARITY
{
    UINT8 m_ucHead1;      //首部1
    UINT8 m_ucHead2;      //首部2
    UINT8 m_ucOptCode;    //操作码
    UINT8 m_ucDataLength; //数据长度
    UINT8 m_szDataBuf[16];//数据
    UINT8 m_ucParity;     //奇偶校验值
}PKT_PARITY;

g. 相对独立的语句组注释。对这一组语句做特别说明,写在语句组上侧,和此语句组之间不留空行,与当前语句组的缩进一致。注意,说明语句组的注释一定要写在语句组上面,不能写在语句组下面。

 

你可能感兴趣的:(嵌入式C语言)