良好的编程风格(一)

爱被打了一巴掌 2022-07-14 16:58 573阅读 0赞

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

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

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

1.排版

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

  1. BOOL BufClr(UINT8 * dest,UINT32 size)
  2. {
  3. if(NULL ==dest || NULL==size)
  4. {
  5. return FALSE;
  6. }
  7. }

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

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

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

  1. void UARTSendAndRecv(UINT8 *ucSendBuf,
  2. UINT8 ucSendLength,
  3. UINT8 *ucRecvBuf,
  4. UINT8 ucRecvLength)
  5. {
  6. }

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

  1. if(bSendEnd)
  2. {
  3. BELL(ON);
  4. }
  5. else
  6. {
  7. BELL(OFF);
  8. }
  9. //--------------------------
  10. for(i=0; i< ucRecvLength; i++)
  11. {
  12. ucRecvBuf[i]=i;
  13. }
  14. //--------------------------
  15. switch(ucintStatus)
  16. {
  17. case USB_INT_EP2_OUT:
  18. {
  19. USBCiEP2Send(USBMainBuf,ucrecvLen);
  20. USBCiEP1Send(USBMainBuf,ucrecvLen);
  21. }
  22. break;
  23. case USB_INT_EP2_IN:
  24. {
  25. USBCiWriteSingleCmd (CMD_UNLOCK_USB);
  26. }
  27. break;
  28. }

2.注释

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

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

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

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

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

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

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

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

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

  1. volatile UINT8 __ucSysMsg=SYS_IDLE;
  2. void SYSSetMsgPriority(void)
  3. {
  4. SYSMSG Msgt;//临时存储消息
  5. UINT8 i;
  6. }

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

  1. /* SYS_MSG_MAP 建立一个消息映射
  2. 宏参数NAME:消息映射表的名字
  3. 宏参数NUM_OF_MSG:消息映射的个数
  4. */
  5. #define SYS_MSG_MAP(NAME,NUM_OF_MSG) do/
  6. { /
  7. DEFINE_MSG_NAME((NAME));/
  8. UINT8 i;/
  9. for(i=0;i< NUM_OF_MSG;i++)/
  10. {/
  11. ININ_CUR_MSG(i)/
  12. }/
  13. }while(0)

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

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

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

发表评论

表情:
评论列表 (有 0 条评论,573人围观)

还没有评论,来说两句吧...

相关阅读