嵌入式C语言进阶之道(C语言编程风格)

所需积分/C币:50 2015-09-22 16:42:10 1.79MB PDF
收藏 收藏 1
举报

嵌入式C语言进阶之道(C语言编程风格)
养成良好的编程风格 一.良好的编程风格 编程的总则:编程首要是要考虑程序的可行性,然后是叫读性、叫移植性、健壮性以及 可测试性。大多数程序员只是关江程序的可行性,而忽略了可读性,可移植性和健壮性,其实 我个人认为,程序的可行性和健壮性与程序的可读性有很大的关系,能写出可读性很好的程 序的程序员,他写的程序的可行性和健壮性必然不会差,也会有不错的可移植性.程序的可读 性需要程序员有一个良好的编程风格. 好风格应该成为一种习惯。如果你在廾始写代码时就关心风格问题,如果你花时间去审 视和改进它,你将会逐渐养成一种好的编稈习惯。一旦这种习惯变成自动的东西,你的潜意 识就会帮你照料许多细节问题,甚至你在上作压力下写出的代码也会更好 1.排版 a.代码缩进空格数为4个。若是可能,尽量用空格来代替Tab键,因为有些编译器不攴持Tab 键(我自己至今未见过,但确实有这个风险),这给稈序的移植带来了问题。在keil中这个 问题很容易解决,只需在在kei主界面的菜单栏点击Edit- Configuration…,弹出 Configuration窗口,点击 Editor标签,在其中C/C+File:、ASM、 Other files栏下,选 μ Insert spaces for tab:复选框,Tab对应的框中填4,这样按tab键就相当于按下四个空 格键。 BOOL BufClr (UINT8 *k dest, UINT32 size) Lif(NULL ==dest NULL==size) 43a√ return FAlse b.较长的语句要分2行来书写,并用‘\’符号隔廾。 uncrc=calcCRC16(Packet p, unlen) ((V if((UINT8) uncrc ! Packet down ser. mCrc[o]\ I( UINT8)(uncrc>>8)!=Packet down ser. mCrc[1]) BELL (ON C.函数代码的参数过长,分多行来书写 void UARTSendAndRecv (UINT8 *uc SendBuf 工NT INT8 ucSendLength, NT8来 uc Recy Buf, UINT8 ucRecvLength d.if、do、 while、 switch、for、case、 default等关键字,必须加上大括号 if(bSendEnd) BELL (ON) 1/7 养成良好的编程风格 else BELL (OFF) for(i=0; i< ucRecvLength; i++) ucRecvBuf[il=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 修改日期:无 2/7 养成良好的编程风格 米 ---一----一一--一-一---一--一一一-一-一—一 米注:本程序定义6个数码管,经过实测,在200Hz~50KHZ时结果较准确,误差小于0.4% 50KHZ以上频率未进行测量.据资料表明,可以测量到120KHZ,木程序未证明. 半米半半半半半半半米米半半米半半半米半半米半米半米*冰半*米字米米米半冰米** tinc lude <xxxx. h> void func ( void) c.函数头应该进行注释,例如函数名称、输入参数、返回值、功能说明。 /*半**半半半将所有参数写入AT24C64共4字节**半*半半*半半半 说明:将表号和用户电量共四字节数据写入AT24c64中 *入口参数: *1数据问接寻址地址buf *2写入到AT24C64的地址字-addh, addr *3写入字节数- count *出口参数1表示写成功,0表示写失败 水冰水水本冰水冰小水冰水冰本水水冰小水水本水半本冰冰水水小水水本水小本水本水冰小冰小水水冰水小水木水示小本水水水水 bit write byte (unsigned char * buf, unsigned char addr unsigned char addr unsigned char count) d.全局变量要注释其功能,若为关键的局部变量同样需要注释其功能。 volatile UInT8 ucSysMSg=SYS IDLE void SYSSetMsgPriority(void SYSMSG Msgt;//临时存储消息 UINT8 1 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)\ 3/7 养成良好的编程风格 I while(0) f.复杂的结构体同样要加上注释。 /*奇偶校验结构体*/ typedef struct PKT PARITY UINT8 m ucHead1;//首部1 UINT8 m ucHead2;//首部2 UINT8 m ucOptCode;//操作码 UINT8 m ucDatalLength;/数据长度 UINI8 m szDataBuf[16];//数据 UINT8 m ucParity;/倚奇偶校验值 JPKT PARITY g.相对独立的语句组注释。对这一组语句做特别说明,写在语句组上侧,和此语句组之间 不留空行,与当前语句组的缩进一致。注意,说明语句组的注释一定要写在语句组上面,不 能写在语句组下面 3标识符 a.变量的命名 方法一:采用匈牙利命名法。命名规则的主要思想是“在变量中加入前缀以增进人们对程序 的理解” 例如半时声明32位整型变量 Length对应使用匈牙利命名法为 unlength。现在列出经常用到 的变量类型 变量类型 示例 char Length unsigned char chEng short int Length unsigned short int usLength int leng unsigned int unLength char *k szBuf unsigned char米 uszBuf volatile unsigned char ucLength 方法 局部变量以小写字母命名 全局变量以首字母大写方式命名(骆驼式); 定义类型和宏定义常数以大写字母命名; 变量的作用域越人,它的名字所带有的信息就应该越多 局部变量: int student age 全局变量: int StudentAge; 宏定义常数:# define student num10 类型定义 typedef InTl6s int (我个人喜欢第二种方法) b.变量命名要注意缩写而且让人简单易懂,若是特别缩写要详细说明。 经常用到的缩写如: 4/7 养成良好的编程风格 Count可缩写为Cnt Message可缩写为Msg Packet可缩写为Pkt Temp可缩写为Tmp 平吋不经常用到的缩写,要注释 Serialcommunication可缩与为 Srlcomm//串口通信变量 Serialcommunicat ionstatus可缩写为 Srlcommstat//串口通信状态变量 C.全局变量和全局函数的命名一定要详细,不惜多用几个单词,例如函数 UARTPrintfstringForlCD 因为它们在整个项目的许多源文件中都会用到,必须让使用者明确这个变量或函数是干什么 用的。局部变量和只在一个源文件中调用的内部函数的命名可以。简略一些,但不能太短, 不要使用单个字母做变量名,只有一个例外:用讠、j、k做循环变量是可以的 d.用」编译廾关的文件头,必须加上当前文件名称,防正编详时严生冲突 例如在 UARTInterface.h头文件中,必须加上以下内容 Ifndef UARTINTERFACE H #define UARTINTERFACE H extern void UARTPrintfString(CONST INT8* str) extern void UARTSendNBytes UINT8 *uc SendBytes, UINT8 ucLen //其他外部声明的代码 Mindif e.禁止用汉语拼音作为标识符名称,可读性极差。呵呵 f.建议名称间的区别要显而易见。使用标识符名称要注意的一个相关问题是发生在名称之 间只有个字符或少数字符不同的情况,特别是名称比较长时,当名称间的区别很容易被误 读时问题就比较显著,比如(数字)和(的小写)、和、和、和,或者和 4.表达式和基本语句 a.不要编写太复杂的复合表达式; 例如: i=a>b&是c<d&&c+f<=g+h;//复合表达式过于复杂 b.不要有多用途的复合表达式; 例如 d=(a =b+c)+r //应拆分为两个语句: b d c如果代码行中的运算符比较多,用括号确定表达式的操作顺序遥免使用默认的优先级 例如 if(a b&& a& c //不良的风格 if((a b)&&(a c)) //良好的风格 注意:只需记住加减运算的优先级低于乘除运算,其它地方一律加上括号 先<) 5/7 养成良好的编程风格 dif语句 da布尔变量与零值比较 不可将布尔变量直接与TRUE、 FALSE或者1、0进行比较。 根据布尔类型的语义,零值为“假”(记为 FALSE),任何非零值都是“貞”(记为RUE)。 TRUE的值究竞是什么并没有统一的标准。例如 Visual c++将TRUE定义为1,而 Visual basic 则将TRIE定义为 例:假设布尔变量名宇为门ag,它与零值比较的标准i语句如下: if (flag) /表示f1ag为真时满足条件 if (!flag /表示fag为假时满足条件 其它的用法都属于不良风格,例如: if (flag = TRUE) if (flag ==1) f (flag == FALSE) if (flag = 0 d.b整型变量与零值比较 应当将整型变量用“=或“!=”直接与0比较 例:假设整型变量为 value,它与零值比铰的标准i语句如下: if (value = 0) if (value! = 0) 不可模仿布尔变量的风格而写成 if (value) //会让人误解 value是布尔变量 f(!value) 小技巧:想必人家都有过将赋值操作符“-”当作比较相等操作符“-”用过,这个错误比 较的隐胨,不易排査,而且编译器从不把这类事情当作是程序员犯下的错。避免的方法有两 种,一种是养成良好的编程惯,在比较数值时小心翼奚的处理;另一种方法见卜面给出的 代码 if(NULL ==p) 是不是觉得这种书写方式很古怪?不是程序写错了? 当然不是! 有经验的程序员为了防止将f(p==NUL)误写成i(p=NUL),而有意把p和NULL颠 倒。编译器认为(p=NULl是合法的,但是会指出(NUL=p是错误的,因为NUL不能 被赋值。所以,再次週到判断整型变量是否与某个数相等时,请这样写吧: if (2==flag) d.c浮点变量与零值比较 不可将浮点变量用“-”或“!”与仟何数字比较。 千万要留意,无论foat还是 double类型变量,都有精度限制。所以一定要避免将浮点变 量用“-”或"!-”与数字比较,应该改法转化成“”或“<”形式。 6/7 养成良好的编程风格 假设浮点变量的名字为x,应当将 if 0.0 //隐含错误的比较 转化为 if(x>= EPSINON&&(x<= EPSINON)/ EPSINO是精度 5杂项 a.一些常量(如圆周率門)或者常需要在调试时修改的参数最好用 define定义,但要注意宏定 义只是简单的替换,因此有些括号不可少。 b.不要轻易调用某些库函数,因为有些厍函数代码很长(我是反对使用prm之类的库函数 的,但是是·家之言,并不勉强各位)。 C.对各运算符的优先级有所了解,记不得没关系,加括号就是,千万不要自作聪明说自己 记得很牢 d.不管有没有无效分支, switch数一定要 defau这个分支。一来让阅读者知道程序员并没 有遗忘 defau,并且防止程序运行过程中出现的意外(健壮性)。 e.函数的参数和返回值没的话最好使用void。 f一些常数和表格之类的应该放到cod中去以节省RA g.程序编完编译看有多少code多少data,注意不要使堆栈为难。 h.减少函数本身或函数间的递归调用 .编写可重入函数时,若使用全局变量,则应通过关中断、信号量(即P、V操作)等手段 对其加以保护 ⅰ.在多重循坏中,应将最忙的循坏放在最内层 k.避免循环体内含判断语句,应将循环语句置于判断语句的代码块之中。 系统运行之初,要初始化有关变量及运行环境,防止未经初始化的变量被引用。 编写代码时要注意随时保存,并定期备份,防止由于断电、硬盘损坏等原因造成代码丢 失 7/7 学会模块化编程 二模块化编程 当你在一个项目小组做一个相对较复杂的工程时,意味着你不再独自单十。你需要和你 的小组成员分工合作,一起完成项目,这就要求小组成员各自负责一部分工程。比如你可能 只是负责通讯或者显示这块。这个吋候,你就应该将自己的这块程序写成个模块,单 独调试,留岀接口供其它模块调用。最后,小组成员都将自己负责的模块写完并调试无误后, 由项目组长进行组合调试刂像这些场合就要求程序必须模块化。模块化的好处是很多的,不 仅仅是使」分工,它还有助于程序的调试,有利」程序结构的划分,还能增加程序的可读性 和可移植忙。 初学者往往搞不懂如何模块化编程,其实它是简单易学,而且又是组织良好程序结构行 之有效的方法之 本文将先大概计一下模块化的方法和注意事项,最后将以初学者使用最广的 keilc编译 器为例,给出模块化编程的详细步骤. 模块化程序设计应该理解以下概述 (1)模块即是一个.c文件和一个.h文件的结合,头文件(h)中是对于该模块接口的声明; 这一条概括了模垬化的实现方法和实质:将一个功能模块的代码单独编写成一个.C文件, 然后把该模坎的接口函数放在.h文件中.举例:假如你用到液晶显示,那么你可能会写一个液 晶驱动模块,以实现字符、汉字和图像的现实,命名为: led device.c,该模块的.c文件大 体可以写成: /冰水**冰**冰*水**水****冰水冰*冰**冰冰冰冰冰水水**冰水*水水*冰水**冰**冰水*冰冰* 液晶驱动模块 文件: lcd device,c *编写人:小瓶盖 *描述:液晶串行显示驱动模块,提供字符、汉字、和图像的实现接口 *编写时间:2009.07.03 米版本:1.2 冰水k水水水水水水水水木冰冰水水水水水水水冰水k水水水冰水水水水水冰冰冰水水冰水水水水水水冰水水水水冰冰水冰水水冰冰水水水水水水水水水水冰 #include /定义变量 unsigned char flag;/局部变量 static unsigned char value;//全局变量 //定义函数 /这是本模块第一个函数,起到延时作用,只供本模块的函数调用,所以用到 static关键字 修饰 /*米*来*****冰**延时子程序***米*冰******米*/ static void delay (uint us) / delay time //这是本模块的第二个函数,要在其他模块中调用 /************写字符程序****半**半***半** *功能:向LCD写入字符 *参数:dat_com为1写入的是数据,为0写入的是指令 /8

...展开详情
试读 75P 嵌入式C语言进阶之道(C语言编程风格)
立即下载 低至0.43元/次 身份认证VIP会员低至7折
    抢沙发
    一个资源只可评论一次,评论内容不能少于5个字
    关注 私信 TA的资源
    上传资源赚积分,得勋章
    最新推荐
    嵌入式C语言进阶之道(C语言编程风格) 50积分/C币 立即下载
    1/75
    嵌入式C语言进阶之道(C语言编程风格)第1页
    嵌入式C语言进阶之道(C语言编程风格)第2页
    嵌入式C语言进阶之道(C语言编程风格)第3页
    嵌入式C语言进阶之道(C语言编程风格)第4页
    嵌入式C语言进阶之道(C语言编程风格)第5页
    嵌入式C语言进阶之道(C语言编程风格)第6页
    嵌入式C语言进阶之道(C语言编程风格)第7页
    嵌入式C语言进阶之道(C语言编程风格)第8页
    嵌入式C语言进阶之道(C语言编程风格)第9页
    嵌入式C语言进阶之道(C语言编程风格)第10页
    嵌入式C语言进阶之道(C语言编程风格)第11页
    嵌入式C语言进阶之道(C语言编程风格)第12页
    嵌入式C语言进阶之道(C语言编程风格)第13页
    嵌入式C语言进阶之道(C语言编程风格)第14页
    嵌入式C语言进阶之道(C语言编程风格)第15页
    嵌入式C语言进阶之道(C语言编程风格)第16页
    嵌入式C语言进阶之道(C语言编程风格)第17页
    嵌入式C语言进阶之道(C语言编程风格)第18页
    嵌入式C语言进阶之道(C语言编程风格)第19页
    嵌入式C语言进阶之道(C语言编程风格)第20页

    试读已结束,剩余55页未读...

    50积分/C币 立即下载 >