编程规范讲义课件.ppt

上传人(卖家):晟晟文业 文档编号:4947280 上传时间:2023-01-27 格式:PPT 页数:80 大小:588.50KB
下载 相关 举报
编程规范讲义课件.ppt_第1页
第1页 / 共80页
编程规范讲义课件.ppt_第2页
第2页 / 共80页
编程规范讲义课件.ppt_第3页
第3页 / 共80页
编程规范讲义课件.ppt_第4页
第4页 / 共80页
编程规范讲义课件.ppt_第5页
第5页 / 共80页
点击查看更多>>
资源描述

1、单击此处键入子标题软件编程规范 引言据说程序员的黄金年代已经过去,听着好象有点感伤的味道。那时候,程序员个个留着长发,不修边幅,光着脚丫子,喜欢抱着键盘坐在地上,写一些别人看不懂他也没想着要别人看懂的东西。今天人们越来越明白软件设计更多地是一种工程,而不是一种艺术,居然有人很恶毒地发明了一种叫软件工程的东西来加速程序员黄金年代的结束。而我们的代码和我们的人本身也不得不渐渐变得西装革履起来。什么是软件编程规范?为了提高源程序的质量和可维护性,最终提高软件产品生产力,对软件产品的源程序的编写风格作出统一的规范约束。风格,约定红宝书:Steve Maguire,编程精粹 为什么要有编程规范?目的:提

2、高源程序的质量和可靠性可读可维护举例:印度软件人员笔试,代码一模一样。GNU编码标准 分类1)语言:C/C,Java,Delphi等2)范围:主机,单板软件 1)我司编程规范怎么形成的?我司的经验 印度和美国公司的文档2)谁维护它?软件工程室 如何使用编程规范?1)开发人员在写代码时按照规范编写2)项目组对开发人员编写的代码进行检查人员:设计、开发、测试、质量形式:结合到其它的检查工作中完成,如代码的正规检视,代码走读对象:所有未归档的重点代码时间:在编码完成、尚未开始调试和单元测试时 公司文件数据库:研发体系文件夹(rnd-apps/huawei)文件名:research_files.nsf

3、华为研发办字199918号 软件编程规范总则华为研发办字199964号 软件编程规范主机、终端、数据库分则华为研发办字199973号 单板软件编程规范 内容两部分内容:一、规则二、常见错误 第一部分 规则以下分两部分给出了一些基本准则,一个是关于程序书写风格的,一个是关于程序质量保证的。每条准则都有例外。如果某人对你说:不能闯红灯,虽然这是一条准则,但你肯定能够举出一种特殊情况,在这种情况下闯红灯倒是个正确的行动。这里关键是要记住准则只是在一般情况下才有意义,因此只有理由十分充足时,才可以违背准则。规则目录1 排版2 注释3 命名4 可读性5 变量6 函数7 可测性8 效率9 质量保证 1 排

4、版1)程序块要采用缩进风格编写,缩进的空格数为4个。2)相对独立的程序块之间、变量说明之后必须加空行。3)长句要分成多行书写说明:长表达式要在低优先级操作符处划分新行,操作 符放在新行之首。例14)对齐只使用空格键,不使用TAB键。4)双目操作符之前、之后或者前后要加空格。5)一行程序以小于80字符为宜。示例1:长语句perm_count_msg.head.len=NO7_TO_STAT_PERM_COUNT_LEN +STAT_SIZE_PER_FRAM*sizeof(_UL);report_or_not_flag=(taskno Criterium,CurrentSession.pDoma

5、in,&SearchCursor);2 注释注释按功能级别可分三类:1.模块(文件)注释;在模块或文件头部进行描述,它对整个模块或文件所要完成的功能进行描述,它的侧重点在于模块关系和功能描述,修改记录一般也放在这里。2.函数(过程)注释;在函数(或过程)前进行描述,例子中给出的就是函数(过程)注释,它主要提供函数(过程)的接口说明,其内容包括基本功能描述、出入口参数、调用关系,如有必要,将实现算法也包括在内。3.代码块注释;在函数(或过程)体中描述,它对某个代码块的功能进行说明,包括对临时变量进行说明。1)有效注释量必须在20以上。2)注释应与其描述的代码相近:上方或右方。3)函数头部应进行注

6、释,列出:函数的目的/功能、输入参数、输出参数、返回值、调用关系(函数、表)等。4)对数据结构的注释应放在其上方相邻位置;对结构中的每个域的注释放在此域的右方。5)全局变量注释包括对其功能、取值范围、哪些函数或过程存取它以及存取时注意事项等的说明。6)对变量的定义和分支语句(条件分支、循环语句等)必须编写注释。7)使用中文注释。例:说明性文件注释/*Copyright,1988-1999,Huawei Tech.Co.,Ltd.File name:/文件名 Author:Version:Date:/作者、版本及完成日期 Description:/用于详细说明此程序文件完成的主要功能,与其他模块

7、 /或函数的接口,输出值、取值范围、含义及参数间的控 /制、顺序、独立或依赖等关系 Others:/其它内容的说明 Function List:/主要函数列表,每条记录应包括函数名及功能简要说明 1.History:/修改历史记录列表,每条修改记录应包括修改日期、修改 /者及修改内容简述 1.Date:Author:Modification:2.*/例:函数注释/*Function:/函数名称 Description:/函数功能、性能等的描述 Calls:/被本函数调用的函数清单 Called By:/调用本函数的函数清单 Table Accessed:/被访问的表(仅对于牵扯到数据库操作的程

8、序)Table Updated:/被修改的表(仅对于牵扯到数据库操作的程序)Input:/输入参数说明,包括每个参数的作 /用、取值说明及参数间关系。Output:/对输出参数的说明。Return:/函数返回值的说明 Others:/其它说明*/例:结构注释/*sccp interface with sccp user primitive message name*/enum SCCP_USER_PRIMITIVE N_UNITDATA_IND,/*sccp notify sccp user unit data come*/N_NOTICE_IND,/*sccp notify user the

9、 No.7 network can not*/*transmission this message*/N_UNITDATA_REQ,/*sccp users unit data transmission request*/;3 标识符命名1)变量命名禁止取单个字符如i、j、k。说明:局部变量如果用单个字符表示,很容易敲错。但 i、j、k作局部循环变量是允许的。2)命名与所使用的系统风格保持一致。说明:如采用UNIX的全小写加下划线的风格或大小写混排 的方式,不要使用大小写与下划线混排的方式;用作 特殊标识如标识成员变量或全局变量的m_和g_,其 后加上大小写混排的方式是允许的。2)匈牙利命名法

10、说到命名约定,就不得不提一下Microsoft的天才程序员Charles Simonyi。他在Xerox的Palo Alto实验室工作时开发了匈牙利式命名约定,该命名法通过在数据和函数名中加入额外的信息以增进程序员对程序的理解。例如:char ch;/*所有的字符变量均以ch开始*/byte b;/*同理*/long l;/*所有的长字均冠以l*/在Microsoft公司中,匈牙利命名法在应用程序部门得到了良好的应用,但在系统部门却并没有得到这样的待遇。实际上,使用此命名法有一个很实际的问题,不容易扩展到处理typedef和C+类。4)命名中的缩写三种方法:1.抽取元音字母 task-tsk

11、user-usr2.取单词意义明显的头部 maximum-max minimum-min3.惯例,实际上是先用(2)后用(1)进行处理而得 temporary-tmp remove-rm限制:如果缩写导致该名字的意义不明确,就不要使用它。示例1:Add_User add_user、AddUser、m_AddUser 示例2:#define _EXAMPLE_0_TEST_#define _EXAMPLE_1_TEST_ void set_sls00(BYTE sls);例:匈牙利命名int liv_Width其变量名解释如下:l 局部变量(Local)(其它:g 全局变量(Global).)i

12、 数据类型(Interger)v 变量(Variable)(其它:c 常量(Const).)Width 变量含义这样可以防止局部变量与全局变量重名。4 可读性1)用括号明确表达式的操作顺序,不使用默认优先级。2)不使用不易理解的数字,用有意义的标识来替代。说明:涉及物理状态或者含有物理意义的常量,不应直 接使用数字,必须用有意义的枚举或宏来代替。3)不要使用难懂的技巧性很高的语句。说明:高技巧语句不等于高效率的程序,实际上程序的 效率关键在于算法。示例:*stat_poi+=1;*+stat_poi+=1;5 变量、结构1)明确公共变量与操作此公共变量的函数或过程的关系,如访问、修改及创建等。

13、说明:明确过程操作变量的关系后,将有利于程序的进 一步优化、单元测试、系统联调以及代码维护等。2)防止局部变量与公共变量同名。说明:若使用了较好的命名规则,那么此问题可自动消除。3)严禁使用未经初始化的变量作为右值。说明:特别是在C/C+中引用未经赋值的指针,经常会 引起系统崩溃。4)公共变量只有一个模块或函数可以修改、创建。说明:降低公共变量耦合度。5)使用严格形式定义的数据类型,不使用与具体硬件或软件环境关系密切的变量。说明:使用标准的数据类型,有利于程序的移植。6)结构:一个功能,一种事务的抽象。说明:设计结构时应力争使结构代表一种现实事务的抽 象,而不是同时代表多种。结构中的各元素应代

14、 表同一事务的不同侧面,而不应把描述没有关系 或关系很弱的不同事务的元素放到同一结构中。7)结构间的关系不要过于复杂。说明:若两个结构间关系较复杂、密切,那么应合为一 个结构。8)若结构中元素个数过多把元素组成不同的子结构。说明:增加结构的可理解性、可操作性和可维护性。9)不使用数据类型默认转换与强制转换。说明:当进行数据类型强制转换时,其数据的意义、转 换后的取值等都有可能发生变化,可能留下隐患。10)使用自定义类型。11)分布式环境或不同CPU间通信环境的数据结构的字节顺序。说明:Intel CPU与Motorola 68360 CPU,在处理位域 及整数时,其在内存存放的“顺序”正好相反

15、。12)在对齐方式下,CPU的运行效率要快得多。示例1:公共变量变量/函数 System_Init Input_Rec Stat_ScoreStudent 创建 修改 访问Score 创建 修改 访问,修改其中,函数Input_Rec、Stat_Score都可修改变量Score,故此变量将引起函数间较大的耦合,并可能增加代码测试、维护的难度。示例2:在DOS下BC3.1环境中代码,在移植时可能产生问题。void main()register int index;/寄存器变量 _AX=0 x4000;/_AX是BC3.1提供的寄存器“伪变量”./program code 示例3:结构typede

16、f struct STUDENT_STRU unsigned char name8;/*student s name*/unsigned char age;/*student s age*/unsigned char sex;/*student s sex,as follows*/*0-FEMALE;1-MALE*/unsigned char teacher_name8;/*the student teacher s name*/unisgned char teacher_sex;/*his teacher sex*/STUDENT;示例4:自定义类型typedef unsigned char

17、 BYTE;typedef unsigned short WORD;typedef unsigned int DWORD;示例5:对齐如下图,当一个long型数(如图中long1)在内存中的位置正好与内存的字边界对齐时,CPU存取这个数只需访问一次内存,而当一个long型数(如图中的long2)在内存中的位置跨越了字边界时,CPU存取这个数就需要多次访问内存,如i960cx访问这样的数需读内存三次(一个BYTE、一个SHORT、一个BYTE,由CPU的微代码执行,对软件透明),所有对齐方式下CPU的运行效率明显快多了。1 8 16 24 32-|long1|long1|long1|long1|

18、-|long2|-|long2|long2|long2|-6 函数1)可重入函数的局部变量的使用。说明:编写C/C+可重入函数时,使用auto即缺省态局 部变量或寄存器变量,不使用static局部变量,否 则必须经过特殊处理,才能使函数具有可重入性。2)编写可重入函数时使用全局变量,通过关中断、信号量(即P、V操作)等手段加以保护。说明:若对所使用的全局变量不加以保护,则此函数就不具 有可重入性,即当多个进程调用此函数时,很有可能 使有关全局变量变为不可知状态。3)对接口函数参数进行合法性检查。说明:这一问题往往有两个极端:要么是调用者和被调用 者对参数均不作合法性检查,造成问题隐患;要么就是

19、调用者和被调用者均对参数进行合法性检 查,产生了冗余代码。4)禁止将函数的参数作为工作变量。说明:将函数的参数作为工作变量,有可能错误地改变参 数内容,很危险。方法:先用局部变量代之,最后再将该局部变量的内容赋 给该参数。5)函数的规模尽量限制在200行以内。说明:不包括注释和空格行。6)一个函数仅完成一件功能。7)非调度函数禁止使用控制参数,只使用数据参数。说明:调度函数是指根据输入的消息类型来启动相应的功 能实体,而本身并不完成具体功能。控制参数是指 改变函数功能行为的参数,即函数要根据此参数来 决定具体怎样工作。非调度函数的控制参数增加了 函数间的控制耦合,使函数间的耦合度增大,并使 函

20、数的功能不唯一。8)检查函数输入的有效性。说明:函数的输入主要有两种:一种是参数输入;另一种是全 局变量、数据文件的输入,即非参数输入。9)不把与函数返回值类型不同的变量进行强制的转换后作为返回值返回。在调用函数填写参数时,不进行默认数据类型转换或强制数据类型转换。10)设计高扇入、合理扇出(小于7)的函数。说明:扇出是指一个函数直接调用(控制)其它函数的数目,而 扇入是指有多少上级函数调用它。函数较合理的扇出通常 是3-5(调度函数除外)。11)不进行函数本身或函数间的递归调用。影响:理解性;系统资源(如栈空间);测试。12)优化函数结构。说明:对初步划分后的函数结构应进行优化。优化原则:(

21、1)不能影响模块功能的实现。(2)考查出错处理和模块的性能要求进行完善。(3)通过分解或合并函数来改进软件结构。(4)规模大的函数要进行分解。(5)降低函数间接口的复杂度。(6)不同层次的函数调用要有较合理的扇入、扇出。(7)函数功能应可预测。(8)提高函数内聚。(单一功能的函数内聚最高)13)禁止使用BOOL参数。说明:1、无意义;2、不利于扩充。示例:重入Exam是int型全局变量,函数Squre_Exam返回Exam平方值。那么如下函数不具有可重入性。unsigned int example(int para)unsigned int temp;Exam=para;/(*)temp=Sq

22、uare_Exam();return temp;此函数若被多个进程调用结果可能是未知的;当(*)语句刚执行完后,另一个使用本函数的进程可能正好被激活,当新激活的进程执行到此函数时,将使Exam赋与另一个不同的para值,所以当控制重新回到“temp=Square_Exam()”后,计算出的temp很可能不是预想中的结果。7 可测性1)统一的调测开关和打印函数。说明:调测打印格式要有统一的形式。信息串中至少要有所在 模块名(或源文件名)及行号。调测开关应分为不同级 别和类型。2)测试代码部分作为一个子模块。3)使用断言来发现问题,提高可测性。说明:断言是对某种假设条件进行检查,可理解为若条件成立

23、则 无动作,否则报告。它可以快速发现并定位软件问题,同 时自动报警。Steve Maguire,编程精粹 4)断言:调测时可能发生的非法情况,正常运行时不应发生。断言处理最终产品肯定会出现且必须处理的错误情况 说明:断言是用来处理不应该发生的错误情况的,对于可能会 发生的且必须处理的情况要写防错程序,而不是断言。如某模块收到其它模块或链路上的消息后,要对消息的 检查是正常的错误检查,不能用断言来实现。5)编写防错程序,在处理错误后用断言宣布发生错误。6)用调测开关来切换软件的DEBUG版和正式版。示例:C语言断言(其中NULL为0L)#ifdef _EXAM_ASSERT_TEST_ /若使用

24、断言测试void exam_assert(char*file_name,unsigned int line_no)printf(nAssert failed:%s,line%un,file_name,line_no);/abort();#define ASSERT(condition)if(condition)/若条件成立,则无动作 NULL;else /否则报告 exam_assert(_FILE_,_LINE_)#else /若不使用断言测试#define EXAM_ASSERT(condition)NULL#endif /*end of ASSERT*/8 程序效率1)在保证软件系统的正

25、确性、稳定性、可读性及可测性的前提下,提高代码效率。2)系统数据结构 程序算法 空间效率例143)循环体内工作量最小化。例154)在多重循环中,应将最忙的循环放在最内层。例16说明:减少CPU切入循环层的次数。5)避免循环体内含判断语句,如果判断语句与循环变量无关,应将循环语句置于判断语句的代码块之中。说明:目的是减少判断次数。6)尽量用乘法或其它方法代替除法。例1:空间效率如下记录学生学习成绩的结构不合理。typedef unsigned char BYTE;typedef unsigned short WORD;typedef struct STUDENT_SCORE_STRU BYTE

26、name8;BYTE age;BYTE sex;BYTE class;BYTE subject;float score;STUDENT_SCORE;分为两个结构,总的存贮空间变小,操作也变得更方便。typedef struct STUDENT_STRU BYTE name8;BYTE age;BYTE sex;BYTE class;STUDENT;typedef struct STUDENT_SCORE_STRU WORD student_index;BYTE subject;float score;STUDENT_SCORE;例:如下代码效率不高。for(ind=0;ind MAX_ADD_

27、NUMBER;ind+)sum+=ind;back_sum=sum;/*backup sum*/语句“back_sum=sum;”完全可以放在for语句之后。例:如下代码效率不高。for(row=0;row 100;row+)for(col=0;col 5;col+)sum+=arowcol;可以改为如下方式,以提高效率。for(col=0;col 5;col+)for(row=0;row 100;row+)sum+=arowcol;9 质量保证1 在软件设计过程中构筑软件质量。2 代码质量保证优先原则。(1)正确性,指程序要实现设计要求的功能。(2)稳定性、安全性,指程序稳定、可靠、安全。(

28、3)可测试性,指程序要具有良好的可测试性。(4)规范/可读性,指程序书写风格、命名规则等要符合规范。(5)全局效率,指软件系统的整体效率。(6)局部效率,指某个模块/子模块/函数的本身效率。(7)个人表达方式/个人方便性,指个人编程习惯。3 只引用属于自己的存贮空间。4 防止引用已经释放的内存空间。5 过程/函数中分配的内存,在过程/函数退出之前要释放。6 过程/函数中申请的(为打开文件而使用的)文件句柄,在过程/函数退出之前要关闭。7 防止内存操作越界。说明:内存操作主要是指对数组、指针、内存地址等的操作。8 系统运行之初,要初始化有关变量及运行环境,防止未经初始化的变量被引用。9 要防止差

29、1错误。说明:此类错误一般是由于把“=”误写成“=”误写成 “”等造成的,由此引起的后果,很多情况下是很严重的,所以当编完程序后,应对这些操作符进行彻底检查。10 注意易混淆的操作符说明:如C/C+中的“=”与“=”、“|”与“|”、“&”与“&”等,若拼写错了,编译器不一定能够检查出来。11 if语句尽量加上else分支,对没有else分支的语句要小心对待;switch语句必须有default分支。12 不使用goto语句。13 时刻注意表达式是否会上溢、下溢。14 使用变量时要注意其边界值的情况。例17 例:变量边界如C语言中字符型变量,有效值范围为-128到127。故以下表达式的计算存在

30、一定风险。char chr=127;int sum=200;chr+=1;/127为chr的边界值,再加1将使chr上溢到-128,而不是128。sum+=chr;/故sum的结果不是328,而是72。若chr与sum为同一种类型,或按如下方式书写,就没有问题sum=sum+chr+1;10 编辑、编译1 要小心地使用编辑器提供的块拷贝功能编程。2 打开编译器的所有告警开关对程序进行编译。3 使用代码检查工具(如C语言用PC-Lint)对源程序检查。4 使用软件工具(如 LogiSCOPE)进行代码审查。11 宏1 用宏定义表达式时,要使用完备的括号。例182 将宏所定义的多条表达式放在大括号

31、中。例193 使用宏时,不允许参数发生变化。例20 例:使用括号#define RECTANGLE_AREA(a,b)a*b#define RECTANGLE_AREA(a,b)(a*b)#define RECTANGLE_AREA(a,b)(a)*(b)正确的定义应为:#define RECTANGLE_AREA(a,b)(a)*(b)例:使用大括号下面的语句只有宏的第一条表达式被执行。#define INTI_RECT_VALUE(a,b)a=0;b=0;INTI_RECT_VALUE(rect.a,rect.b);正确的用法应为:#define INTI_RECT_VALUE(a,b)a

32、=0;b=0;INTI_RECT_VALUE(rect.a,rect.b);例:参数变化示例:如下用法可能导致错误。#define SQUARE(a)(a)*(a)int a=5;int b;b=SQUARE(a+);/结果:a=7,即执行了两次增1。正确的用法是:b=SQUARE(a);a+;/结果:a=6,即只执行了一次增1。第二部分 常见错误通过对常见错误的整理,使大家不再犯类似的错误 1 指针操作使用指针虽然灵活,但也对程序的稳定性造成一定威胁,主要原因是当要操作一个指针时,此指针可能正指向一个非法的地址。因此每个开发人员都必须格外小心,以防引起错误,并且在使用指针前最好对其合法性进行

33、检查(比如用断言或直接检查指针是否合法等手段)。安安全全地使用一个指针并不是一件容易的事,所以在没有必要使用指针的地方,就别用。_UC*puc_card_config_tab;.Get_Config_Table(AMP_CPM_CARD_CONFIG_TABLE,&ul_card_config_num,&puc_card_config_tab,use_which_data_area);.b_middle_data_ok=generate_trans_middle_data_from_original_data(puc_card_config_tab,Ul_card_config_num)其中红

34、色部分巧妙的利用指向指针的指针为指针puc_card_config_tab赋值,而在兰色部分使用该指针。但在Get_Config_Table函数中有可能失败返回而不给该指针赋值。因此,以后使用的可能是一个非法指针。2 公共变量的操作公共变量是引起程序不稳定的另一个主要因素,因此公共变量除了要有详细的注释说明外,引用时还应特别注意。比如某公共变量Current_Task_No,合法值为0100,那么当你每次修改它时都要确认修改后的值为正确范围;当引用时,应首先判断其合法性(根据实际情况,可用断言或直接判断)。故编程时应尽量少用公共变量,而没有必要的公共变量更是多余的。3 局部变量的使用 关于局部

35、变量,应注意以下问题:由于非static局部变量(在程序运行到此函数时)占用的是堆栈空间,故不应声明得过大,否则容易造成堆栈溢出。较大的局部变量最好声明成static变量。假如某函数的返回值为指针型,那么不可把非static的局部变量的地址作为返回值返回。非static局部变量的值,在函数返回后将会消失,而static局部变量则不会,编程时要注意它们的区别。4 不经意的赋值语句 如:if (Connection_State index .state =STATE_IDLE )写成:if (Connection_State index .state =STATE_IDLE )建议在比较判断语句中

36、,把常量放在前面,这样编译器就可查出这种错误。如:if (STATE_IDLE =Connection_State index .state )5 函数中分配了内存,但退出时没有释放它 这肯定是由于粗心造成的,每个开发人员都知道这是错误,但据出去开局的开发人 员讲,在我们的正式软件版本中确确实实发现过这种事情。比如在某个函数中,一开始分配了一块内存,在函数处理过程中,有个出错后返回 的处理,若此返回没有释放所分配的内存,那么在这儿就留下了一个隐患。下面举几种常见的内存泄漏错误:1.函数有多个出口时,没有在每个出口处对动态申请的内存进行释放。一般在异常处理时容易出现这种错误。例:pRecord=

37、new charpTable-GetRecordLength();assert(pRecord!=NULL);if(pTable-GoTop(FALSE)!=DBIERR_NONE)return;/如果从这里返回,pRecord将得不到释放2.给指针赋值时,没有检查指针是否为空,如果指针不为空,那么指针原来指向的内存将丢失。如:struct FileInfo*pdbffile=new struct FileInfo;pdbffile-pfileinfo=new struct ffblk;pdbffile-srcname=srcRootPath;pdbffile-desname=desRootP

38、ath;pdbffile-prev=NULL;pfile=pdbffile;赋值之前没有检查一下pfile是否为空,如果不为空,会造成pfile指向的内存丢失。3.连续二次内存动态分配,在第二次分配失败时,忘记释放第一次已经申请到的内存。.pMsgDB_DEV=(PDBDevMsg)GetBuff(sizeof(DBDevMsg),_LINE_);if(pMsgDB_DEV=NULL)return;pMsgDBApp_To_Logic=(LPDBSelfMsg)GetBuff(sizeof(DBSelfMsg),_LINE_);if(pMsgDBApp_To_Logic=NULL)return

39、;/此处返回造成pMsgDB_DEV指向的内存丢失4.代码中缺少应有的条件分支处理,导致程序未执行任何操作而退出时,也可能没有释放应释放的内存,这种情况一般是缺少应有的else分支,或switch语句的default分支没有应有的处理。static void OncePowerCmdHandle(struct HT_Appmsg *msg)pPower_test_answer=(struct _oncepower_test_answer*)GetBuff(sizeof(struct _oncepower_test_answer),_LINE_);if(pPower_test_answer=NU

40、LL_PTR)return;.if(TSS_Statetestpsn.state=TEST_DEV_BUSY|TSS_Statetestpsn.state=TEST_DEV_ERROR).else if(TSS_Statetestpsn.state=TEST_DEV_IDLE)./缺少 else 分支,可能造成 pPower_test_answer 得不到释放6 差1错误 此类错误一般是由于把=写成=写成等造成的,由此引起的 后果,很多情况下是很严重的,所以编程时,一定要在这些地方万分小心。7 使用已释放的内存 在程序中引用已经释放了的内存。8 数据上溢或下溢,数组的越界等 如:假设size为

41、unsigned char类型变量,那么 while (size-=0 )./program 将出现下溢,因为当size等于0时,再减1后不会小于0,而是0 xFF,所以程序实际上是一个死循环。void Cell_CBCH_Load_Static(struct MsgCB FAR*pMsg)。memcpy(_UC*)&tmp_msg,pMsg,sizeof(tmp_msg);pMsg=pMsg+sizeof(tmp_msg);/sizeof(tmp_msg)=10;本意是想移动10个字节,可是实际上指针移动了10*sizeof(struct MsgCB)个字节;CellNum=tmp_msg.

42、usCellNum;。所以结构指针传入函数后,如要进行指针移动操作,最好先将其转化为_UC型再说。总之指针操作要小心为上。9 运算符优先级错误如word =high 8 +low;语句本意是把字节high与low合成一个字,但由于比+优先级低,故结果不对。应改成如下之一:word =high 8|low ;word =high *256 +low ;word =(high 8 )+low ;10 编写非单一功能的函数先看一下C运行库手册中一个函数的描述void*realloc(void*block,size_t size);DescriptionReallocates main memory.

43、realloc attempts to shrink or expand the previously allocated block to size bytes.If size is zero,the memory block is freed and NULL is returned.The block argument points to a memory block previously obtained by calling malloc,calloc,or realloc.If block is a NULL pointer,realloc works just like mall

44、oc.realloc adjusts the size of the allocated block to size,copying the contents to a new location if necessary.Return Valuerealloc returns the address of the reallocated block,which can be different than the address of the original block.If the block cannot be reallocated,realloc returns NULL.If the

45、 value of size is 0,the memory block is freed and realloc returns NULL.看看realloc是不是一个实现得面面俱到的最好例子?它在一个函数中完成了所有的内存管理工作。既然如此,还要malloc干什么?还要free干什么?realloc全包了。有几个很好的理由说明我们不应该这样设计函数。首先,这样的函数很难指望程序员安全地使用。它包括了如此之多的细节,甚至许多有经验的程序员都不全知道。另一个问题是:我们知道传递给realloc的可能是无用信息,但是因为其定义如此通用使它很难防范无效的参数。如果错误地给它传递了NULL指针,合法

46、;如果错误地给它传递了为零的块长,也合法。如果实际上任何参数都合法,那么我们怎样用断言检查其参数的有效性呢?甚至在极端的情况下也是如此,一个极端是释放内存块,另一个极端是分配内存块。这是两种截然相反的两种功能。产生多功能的函数几乎总是两个原因:一个是其多种功能是逐步演变而来的;另一个是具体的实现为其增加了多余的功能,为不包括这些所谓的幸运功能,实现该函数的程序员扩展了相应的形式描述。但不管出于什么理由编写了多功能的函数,都要把它分解为不同的功能。这里有一个重要的原则:不要编写多种功能集于一身的函数。为了对参数进行更强的确认,要编写功能单一的函数。12 不同数据类型之间的比较操作在循环终止条件的

47、判断中,不同类型变量的比较操作容易造成死循环。int i;.for(i=1;idwLen/2;i+)wCheckSum=(*pCheck);pCheck+;return(wCheckSum);该段代码是在DOS环境下用BC编译的,循环变量i是int型(2个字节),而dwLen是DWORD型(4个字节),如果dwLen大于65536,那么该函数就是死循环了。11、公共资源的互斥性和竞用性例:测试板间通信性能。从接口板A向接口板B循环发送消息,通过超级终端观察消息的收发情况。测试结果:每发送一定数量的消息帧后,会出现发送地址出错现象。原因:接收板回送缓冲区指针给发送板,是采用memcpy单字节拷贝的方式。若发送速度快于接收速度,两板竞用发送板系统总线访问缓冲区指针所在的共享内存,导致数据访问冲突。memcpy过程被打断,即出现发送板读发送地址出错现象。采用四字节拷贝函数bcopyLongs传送发送缓冲区指针,问题解决。The end

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 办公、行业 > 各类PPT课件(模板)
版权提示 | 免责声明

1,本文(编程规范讲义课件.ppt)为本站会员(晟晟文业)主动上传,163文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。
2,用户下载本文档,所消耗的文币(积分)将全额增加到上传者的账号。
3, 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(发送邮件至3464097650@qq.com或直接QQ联系客服),我们立即给予删除!


侵权处理QQ:3464097650--上传资料QQ:3464097650

【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。


163文库-Www.163Wenku.Com |网站地图|