C语言编程规范v1.0

上传人:黑** 文档编号:55772470 上传时间:2022-02-18 格式:DOCX 页数:56 大小:74.24KB
返回 下载 相关 举报
C语言编程规范v1.0_第1页
第1页 / 共56页
C语言编程规范v1.0_第2页
第2页 / 共56页
C语言编程规范v1.0_第3页
第3页 / 共56页
点击查看更多>>
资源描述
深圳市吉祥腾达科技有限公司C语言编程规范修订记录版本修改原因/内容作者口期批准VI. 0初始版本:参考业界普遍使用的原则、规则、建议。鲁超军2015-09-23原则2.1 一个函数仅完成一件功能。说明:一个函数实现多个功能给开发、使用、维护都带来很大的困难。将没有关联或者关联很弱的语句放到同一函数中,会导致函数职责不明确,难以理解,难以测试和改动。案例:realloco在标准C语言中,realloc是一个典型的不良设计。这个函数基本功能是重新分配内存,但它承担了太多的其他任务:如果传入的指针参数为NULL就分配内存,如果传入的大小参数为0就释放内存,如果可行则就地重新分配,如果不行则移到其他地方分配。如果没有足够可用的内存用来完成重新分配(扩大原来的内存块或者分配新的内存块),则返回NULL,而原来的内存块保持不变。这个函数不易扩展,容易导致问题。例如下面代码容易导致内存泄漏:char * buffer = (char *)malloc(XXX_SIZE);buffer = (char *)realloc(buffer, NEW_SIZE);如果没有足够可用的内存用来完成重新分配,函数返回为NULL,导致buffer原来指向的内存被丢失。延伸阅读材料:敏捷软件开发:原则、模式与实践第八章,单一职责原则(SRP)原则2.2重复代码应该尽可能提炼成函数。说明:重复代码提炼成函数可以带来维护成本的降低。在“代码能用就不改”的指导原则之下,大量的烟囱式设计及其实现充斥着各产品代码之中。新需求增加带来的代码拷贝和修改,随着时间的迁移,产品中堆砌着许多类似或者重复的代码。当一段代码重复两次时,即应考虑消除重复,当代码重复超过三次时,应当立刻着手消除重复。一般情况下,可以通过提炼函数的形式消除重复代码。规则2.1避免函数过长,新增函数不超过50行(非空非注释行)。说明:本规则仅对新增函数做要求,对已有函数修改时,建议不增加代码行。过长的函数往往意味着函数功能不单一,过于复杂(参见原则2.1: 一个函数只完成一个功能)。函数的有效代码行数,即NBNC (非空非注释行)应当在1, 50呕间。例外:某些实现算法的函数,由于算法的聚合性与功能的全面性,可能会超过50行。延伸阅读材料:业界普遍认为一个函数的代码行不要超过一个屏幕,避免来回翻页影响阅读;一般的代码度量工具建议都对此进行检查,例如Logiscope的函数度量:Number of Statement(函数中的可执行语句数)建议不超过20行,QAC建议一个函数中的所有行数(包括注释和空白行)不超过50行。规则2.2避免函数的代码块嵌套过深,新增函数的代码块嵌套不超过4层。说明:本规则仅对新增函数做要求,对已有的代码建议不增加嵌套层次。函数的代码块嵌套深度指的是函数中的代码控制块(例如:if、for、whiles switch等)之间互相包含的深度。每级嵌套都会增加阅读代码时的脑力消耗,因为需要在脑子里维护一个“栈”(比如,进入条件语句、进入循环)。应该做进一步的功能分解,从而避免使代码的阅读者一次记住太多的上下文。优秀代码参考值:1,4。规则2.3可重入函数应避免使用共享变量;若需要使用,则应通过互斥手段(关中断、信号量)对其加以保护。说明:可重入函数是指可能被多个任务并发调用的函数。在多任务操作系统中,函数具有可重入性是多个任务可以共用此函数的必要条件。共享变量指的全局变量和static变量。编写C语言的可重入函数时,不应使用static局部变量,否则必须经过特殊处理,才能使函数具有可重入性。示例:函数square_exam返回g_exam平方值。那么如下函数不具有可重入性。int g_exam:unsigned int example( int para )(unsigned int temp;g_exam = para; / (*)temp 二 square_exam ();return temp;此函数若被多个线程调用的话,其结果可能是未知的,因为当(*)语句刚执行完后,另外一个使用本函数的线程可能正好被激活,那么当新激活的线程执行到此函数时,将使g_exam赋于另一个不同的para值,所以当控制重新回到“temp =square_exam ()”后,计算出的temp很可能不是预想中的结果。此函数应如下改进。int g_exam;unsigned int example( int para )(unsigned int temp;申请信号量操作 /若申请不到“信号量。说明另外的进程正处于g.exam = para;/给g_exam赋值并计算其平方过程中(即正在使用此temp二square_exani( ); /信号),本进程必须等待其释放信号后,才可继释放信号量操作/续执行。其它线程必须等待本线程释放信号量后/才能再使用本信号。return temp;规则2.4对参数的合法性检查,由调用者负责还是由接口函数负责,应在项目组/模块内应统一规定。缺省由调用者负责。说明:对于模块间接口函数的参数的合法性检查这一问题,往往有两个极端现象,即:要么是调用者和被调用者对参数均不作合法性检查,结果就遗漏了合法性检查这一必要的处理过程,造成问题隐患;要么就是调用者和被调用者均对参数进行合法性检查,这种情况虽不会造成问题,但产生了冗余代码,降低了效率。规则2.5对函数的错误返回码要全面处理。说明:一个函数(标准库中的函数/第三方库函数/用户定义的函数)能够提供一些指示错误发生的方法。这可以通过使用错误标记、特殊的返回数据或者其他手段,不管什么时候函数提供了这样的机制,调用程序应该在函数返回时立刻检查错误指示。示例:下面的代码导致宕机FILE *fp = fopen( /writeAlarmLastTime, log, r);if(fp = NULL)(return;char buff 128=fscanf (fp, 0)ul = (unsigned char) *sl+;u2 = (unsigned char) *s2+;if (ul != u2)return ul u2;if* (ul = 0)return 0:return 0;延伸阅读:pc-lint 8.0 的帮助材料(pc-lint.pdf) 11.4 const Checking建议2.2函数应避免使用全局变量、静态局部变量和I/O操作,不可避免的地方应集中使用。说明:带有内部“存储器”的函数的功能可能是不可预测的,因为它的输出可能取决于内部存储器(如某标记)的状态。这样的函数既不易于理解又不利于测试和维护。在C语言中,函数的static局部变量是函数的内部存储器,有可能使函数的功能不可预测,然而,当某函数的返回值为指针类型时,则必须是static的局部变量的地址作为返回值,若为auto类,则返回为错针。示例:如下函数,其返回值(即功能)是不可预测的。unsigned int integer_sum Q unsigned int base )(unsigned int index;static unsigned int sum = 0; / 注意,是static类型的。/若改为冲七歧型,则函数即变为可预测。for (index = 1; index get_first_child(&log_item) ; / list, xml 为空,导致读出log_item为空 . hr 二 log_item-get_next_sibling(&media_next_node) : ./ log_item为空,导致宕机正确写法:确保读出的内容非空。hr = root_node-get_first_child(&log_item); if (log_item = NULL)/确保读出的内容非空(return retValue;hr 二 log_item-get_next_sibling(&media_next_node);建议2.4函数的参数个数不超过5个。说明:函数的参数过多,会使得该函数易于受外部(其他部分的代码)变化的影响,从而影响维护工作。函数的参数过多同时也会增大测试的工作量。函数的参数个数不要超过5个,如果超过了建议拆分为不同函数。建议2.5除打印类函数外,不要使用可变长参函数。说明:可变长参函数的处理过程比较复杂容易引入错误,而且性能也比较低,使用过多的可变长参函数将导致函数的维护难度大大增加。建议2.6源文件范围内声明和定义的所有函数,除非外部可见,否则应该增加static关键字。说明:如果一个函数只是在同一文件中的其他地方调用,那么就用static声明。使用static确保只是在声明它的文件中是可见的,并且避免了和其他文件或库中的相同标识符发生混淆的可能性。建议定义一个STATIC宏,在调试阶段,将STATIC定义为static,版本发布时,改为空,以便于后续的打热补丁等操作。#ifdef _DEBUG#define STATIC static#else#define STATICftendif3标识符命名与定义3.1通用命名规则原则3.1标识符的命名要清晰、明了,有明确含义,同时使用完整的单词或大家基本可以理解的缩写,避免使人产生误解。说明:尽可能给出描述性名称,不要节约空间,让别人很快理解你的代码更重要。示例:好的命名:int error_number;int number_of_completed_connection;不好的命名:使用模糊的缩写或随意的字符:int n;int nerr;int n_comp_conns;原则3.2除了常见的通用缩写以外,不使用单词缩写,不得使用汉语拼音。说明:较短的单词可通过去掉“元音”形成缩写,较长的单词可取单词的头几个字母形成缩写,一些单词有大家公认的缩写,常用单词的缩写必须统一。协议中的单词的缩写与协议保持一致。对于某个系统使用的专用缩写应该在注视或者某处做统一说明。一些常见可以缩写的例子:argument可缩写为argbuffer可缩写为buffclock可缩写为elkcommand可缩写为emdcompare可缩写为empconfiguration 可缩写为 cfgdevice可缩写为deverror可缩写为errhexadecimal 可缩写为 hexincrement可缩写为incinitialize 可缩写为 initmaximum 可缩写为 maxmessage可缩写为msgminimum 可缩写为 minparameter 可缩写为 paraprevious可缩写为prevregister可缩写为regsemaphore 可缩写为 semstatistic 可缩写为 statsynchronize 可缩写为 synctemp可缩写为tmp规则3.1产品/项目组内部应保持统一的命名风格。说明:Unix like和windows like风格均有其拥楚,产品应根据自己的部署平台,选择其中一种,并在产品内部保持一致。例外:即使产品之前使用匈牙利命名法,新代码也不应当使用。建议3.1用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。示例:add/removeget/releaseopen/closesource/targetup/downbegin/endcreate/destroyincrement/decrement put/getmin/maxold/newshow/hidesend/receiveinsert/deleteadd/deletefirst/1 a stlock/unlocksta rt/sto pn ext/p revioussource/destination copy/paste建议3.2尽量避免名字中出现数字编号,除非逻辑上的确需要编号。示例:如下命名,使人产生疑惑。#define EXAMPLE_O_TEST_#define EXAMPLE_1_TEST_应改为有意义的单词命名#define EXAMPLE_UNIT_TEST_#define EXAMPLE_ASSERT_TEST_建议3.3平台/驱动等适配代码的标识符命名风格保持和平台/驱动一致。说明:涉及到外购芯片以及配套的驱动,这部分的代码变动(包括为产品做适配的新增代码),应该保持原有的风格。建议3.4重构/修改部分代码时,应保持和原有代码的命名风格一致。说明:根据源代码现有的风格继续编写代码,有利于保持总体一致。3.2文件命名规则建议3.5文件命名统一采用小写字符。说明:因为不同系统对文件名大小写处理会不同(如MS的DOS、Windows系统不区分大小写,但是Linux系统则区分),所以代码文件命名建议统一采用全小写字母命名。3.3变量命名规则规则3.2全局变量应增加“g_”前缀。规则3.3静态变量应增加“s_”前缀。说明:增加g_前缀或者s_前缀,原因如下:首先,全局变量十分危险,通过前缀使得全局变量更加醒目,促使开发人员对这些变量的使用更加小心。规则3.4禁止使用单字节命名变量,但允许定义i、j、k作为局部循环变量。建议3.6不建议使用匈牙利命名法。说明:变量命名需要说明的是变量的含义,而不是变量的类型。在变量命名前增加类型说明,反而降低了变量的可读性;更麻烦的问题是,如果修改了变量的类型定义,那么所有使用该变量的地方都需要修改。匈牙利命名法源于微软,然而却被很多人以讹传讹的使用。而现在即使是微软也不再推荐使用匈牙利命名法。历来对匈牙利命名法的一大诟病,就是导致了变量名难以阅读,这和本规范的指导思想也有冲突,所以本规范特意强调,变量命名不应采用匈牙利命名法,而应想法使变量名为一个有意义的词或词组,方便代码的阅读。建议3.7使用名词或者形容词+名词方式命名变量。3.4函数命名规则建议3.8函数命名应以函数要执行的动作命名,一般采用动词或者动词+名词的结构。示例:找到当前进程的当前目录DWORD GetCurrentDirectory( DWORD BufferLength, LPTSTR Buffer);建议3.9函数指针除了前缀,其他按照函数的命名规则命名。3.5宏的命名规则规则3.5对于数值或者字符串等等常量的定义,建议采用全大写字母,单词之间加下划线一的方式命名(枚举同样建议使用此方式定义)。示例:#define PI_ROUNDED 3.14规则3.6除了头文件或编译开关等特殊标识定义,宏定义不能使用下划线开头和结尾。说明:一般来说,开头、结尾的宏都是一些内部的定义,ISO/IEC 9899 (俗称C99)中有如下的描述(6.10.8 Predefined macro names):None of these macro names, nor the identifier defined, shall be the subject of a ftdefine or a #undef preprocessing directive. Any other predefined macro names shall begin with a leading underscore followed by an uppercase letter or a second underscore.延伸阅读材料:代码大全第2版(Steve McConnell著金戈/汤凌/陈硕/张菲译电子工业出版社2006年3月)“第11章变量命的力量“。4变量原则4.1 一个变量只有一个功能,不能把一个变量用作多种用途。说明:一个变量只用来表示一个特定功能,不能把一个变量作多种用途,即同一变量取值不同时,其代表的意义也不同。市例:具有两种功能的反例WORD DelRelTimeQue (void)WORD Locate;Locate = 3;Locate = DeleteFromQue (Locate) ; /* Locate具有两种功能:位置和函数DeleteFromQue的退回值*/return Locate;正确做法:使用两个变量WORD DelRelTimeQue (void)WORD Ret;WORD Locate;Locale =3:ReX = DeleteFromQne(Locate);return Ret;原则4.2结构功能单一;不要设计面面俱到的数据结构。说明:相关的一组信息才是构成一个结构体的基础,结构的定义应该可以明确的描述一个对象,而不是一组相关性不强的数据的集合。设计结构时应力争使结构代表一种现实事务的抽象,而不是同时代表多种。结构中的各元素应代表同一事务的不同侧面,而不应把描述没有关系或关系很弱的不同事务的元素放到同一结构中。示例:如下结构不太清晰、合理。typedef struct STUDENT_STRUunsigned char name32;/*students name */unsigned char age;/*students age */unsigned char sex;/*students sex, as follows */*0-FEMALE; 1-MALE */unsigned char teacher_name32; /* the student teachers name */unsigned char teacher_sex; /* his teacher sex */ STUDENT;若改为如下,会更合理些。typedef struct TEACHER_STRU(unsigned char name32;/* teacher name */unsigned char sex;/* teacher sex, as follows */*0-FEMALE; 1-MALE */unsigned int teacherjnd; /* teacher index */ TEACHER;typedef struct STUDENT_STRU(unsigned char name32;/*studentsname*/unsigned char age;/*studentsage */unsigned char sex;/*studentssex, as follows */*0-FEMALE; 1-MALE */unsigned int teacherjnd; /* his teacher index */ STUDENT;原则4.3不用或者少用全局变量。说明:单个文件内部可以使用static的全局变量,可以将其理解为类的私有成员变量。全局变量应该是模块的私有数据,不能作用对外的接口使用,使用static类型定义,可以有效防止外部文件的非正常访问。规则4.1防止局部变量与全局变量同名。说明:尽管局部变量和全局变量的作用域不同而不会发生语法错误,但容易使人误解。规则4.2通讯过程中使用的结构,必须注意字节序。说明:通讯报文中,字节序是一个重要的问题,cpu类型复杂多样,大小端、32位/64位的处理器也都有,如果结构会在报文交互过程中使用,必须考虑字节序问题。由于位域在不同字节序下,表现看起来差别更大,所以更需要注意。对于这种跨平台的交互,数据成员发送前,都应该进行主机序到网络序的转换;接收时,也必须进行网络序到主机序的转换。规则4.3严禁使用未经初始化的变量作为右值。说明:坚持建议4.3 (在首次使用前初始化变量,初始化的地方离使用的地方越近越好。)可以有效避免未初始化错误。建议4.1构造仅有一个模块或函数可以修改、创建,而其余有关模块或函数只访问的全局变量,防止多个不同模块或函数都可以修改、创建同一全局变量的现象。说明:降低全局变量耦合度。建议4.2使用面向接口编程思想,通过API访问数据:如果本模块的数据需要对外部模块开放,应提供接口函数来设置、获取,同时注意全局数据的访问互斥。说明:避免直接暴露内部数据给外部模型使用,是防止模块间耦合最简单有效的方法。定义的接口应该有比较明确的意义,比如一个风扇管理功能模块,有自动和手动工作模式,那么设置、查询工作模块就可以定义接口为SetFanWorkMode, GetFanWorkMode;查询转速就可以定义为GetFanSpeed;风扇支持节能功能开关,可以定义EnabletFanSavePower等等。建议4.3在首次使用前初始化变量,初始化的地方离使用的地方越近越好。说明:未初始化变量是C和C+程序中错误的常见来源。在变量首次使用前确保正确初始化。在较好的方案中,变量的定义和初始化要做到亲密无间。示例:不可取的初始化:无意义的初始化int speedup_factor = 0;if (condition)speedup_factor = 2;else(speedup_factor = -1;不可取的初始化:初始化和声明分离int speedup_factor;if (condition)目录目录1简介20规范制订说明20.1代码总体原则20.2术语定义21头文件31.1背景3I. 2术语定义:32函数82.1背景83标识符命名与定义133.1通用命名规则133.2文件命名规则153.3变量命名规则153.4函数命名规则163.5宏的命名规则164变量165宏、常量196质量保证227程序效率258注释269排版与格式2810表达式2911安全性31II. 1字符串操作安全3211.2整数安全3311.3格式化输出安全3411.4文件I/O安全3611.5 其它37speedup_factor = 2;elsespeedup_factor = -1;较好的初始化:使用默认有意义的初始化int speedup_factor = -1;if (condition)(speedup_factor = 2;较好的初始化使用?:减少数据流和控制流的混合int speedup_factor = condition?2:-l;较好的初始化:使用函数代替复杂的计算流int speedup_factor = ComputeSpeedupFactor();建议4.4明确全局变量的初始化顺序,避免跨模块的初始化依赖。说明:系统启动阶段,使用全局变量前,要考虑到该全局变量在什么时候初始化,使用全局变量和初始化全局变量,两者之间的时序关系,谁先谁后,一定要分析清楚,不然后果往往是低级而又灾难性的。建议4.5尽量减少没有必要的数据类型默认转换与强制转换。说明:当进行数据类型强制转换时,其数据的意义、转换后的取值等都有可能发生变化,而这些细节若考虑不周,就很有可能留下隐患。示例:如下赋值,多数编译器不产生告警,但值的含义还是稍有变化。char ch;unsigned short int exam;ch = -1;exam = ch; /编译器不产生告警,此时exam为OxFFFF。5宏、常量规则5.1用宏定义表达式时,要使用完备的括号。说明:因为宏只是简单的代码替换,不会像函数一样先将参数计算后,再传递。示例:如下定义的宏都存在一定的风险#define RECTANGLE_AREA(a, b) a * bttdefine RECTANGLE_AREA(a, b) (a * b)#define RECTANGLE_AREA(a, b) (a) * (b)正确的定义应为:ftdefine RECTANGLE_AREA(a, b) (a) * (b)规则5.2将宏所定义的多条表达式放在大括号中。说明:更好的方法是多条语句写成do while(O)的方式。示例:看下面的语句,只有宏的第一条表达式被执行。#define FOO(x) printf(arg is %dn, x); do_something_useful(x);为了说明问题,下面for语句的书写稍不符规范for (blah = 1; blah (b) ? (a) : (b)intMAX_FUNC(int a, int b):(b);return (a) (b) ? (a)inttestFunc ()unsigned int a=1:int b = 1;printf(MACRO:max of aand bis :%dn”,MAX_MACRO(+a, b);printf CFUNC :max of aand bis :MAX_FUNC (a, b);return 0;上面宏代码调用中,结果是(a goto continue、break等改变程序流程的语句。说明:如果在宏定义中使用这些改变流程的语句,很容易引起资源泄漏问题,使用者很难自己察觉。示例:在某头文件中定义宏CHECK_AND_RETURN:#define CHECK_AND_RETURN(cond, ret) (if (cond = NULL_PTR) return ret;然后在某函数中使用(只说明问题,代码并不完整):pMeml = VOS_MemAlloc(.);CHECK_AND_RETURN(pMeml, ERR_CODE_XXX)pMem2 = VOS_MemAlloc(.);CHECK_AND_RETURN(pMem2 ERR_CODE_XXX)/*此时如果pMem2=NULL_PTR,贝lj pMeml未释放函数就返回了,造成内存泄漏。*/所以说,类似于CHECK_AND_RETURN这些宏,虽然能使代码简洁,但是隐患很大,使用须谨慎。6质量保证原则6.1代码质量保证优先原则1. 正确性,指程序要实现设计要求的功能。2. 简洁性,指程序易于理解并且易于实现。3. 可维护性,指程序被修改的能力,包括纠错、改进、新需求或功能规格变化的适应能力。4. 可靠性,指程序在给定时间间隔和环境条件下,按设计要求成功运行程序的概率。5. 可测试性,指软件发现故障并隔离、定位故障的能力,以及在一定的时间和成本前提下,进行测试设计、测试执行的能力。6. 性能高效,指是尽可能少地占用系统资源,包括内存和执行时间。7. 可移植性,指为了在原来设计的特定环境之外运行,对系统进行修改的能力。8. 个人表达方式/个人方便性,指个人编程习惯。原则6.2要时刻注意易混淆的操作符。说明:包括易混淆和的易用错操作符1、易混淆的操作符C语言中有些操作符很容易混淆,编码时要非常小心。赋值操作符“二”逻辑操作符关系操作符位操作符关系操作符“”位操作符“”逻辑操作符“II”位操作符T逻辑操作符“&”位操作符逻辑操作符叩位操作符2、易用错的操作符(1)除操作符“/“:当除操作符的运算量是整型量时,运算结果也是整型。如:1/2=0 求余操作符“”:求余操作符“”的运算量只能是整型。如:5%2=1,而5.0%2是错误的。自加、自减操作符“+”a v、 :k = 5; x = k+;执行后,x = 5,k = 6k = 5; x = +k;执行后,x = 6,k = 6k = 5; x = k-;执行后,x = 5,k = 4k = 5; x = -k;执行后,x = 4, k = 4规则6.1禁止内存操作越界。说明:内存操作主要是指对数组、指针、内存地址等的操作。内存操作越界是软件系统主要错误之一,后果往往非常严重,所以当我们进行这些操作时一定要仔细小心。示例:使用itoa ()将整型数转换为字符串时:char TempShold10itoa(ProcFrecy, TempShold, 10); /*刷新间隔设为值1073741823时,监控前台抛异常。*/TempShold是以0结尾的字符数组,只能存储9个字符,而ProcFrecy的最大值可达到10位,导致符数组TempShold越界。正确写法:一个int (32位)在一21474836472147483648之间,将数组TempShold设置成12位。char TempShold12itoa(ProcFrecy,TempShold,10);坚持下列措施可以避免内存越界:数组的大小要考虑最大情况,避免数组分配空间不够。避免使用危险函数 sprintf /vsprintf/strcpy/strcat/gets操作字符串,使用相对安全的函数snprintf/strncpy/strncat/fgets代替。使用memcpy/memset时一定要确保长度不要越界字符串考虑最后的0,确保所有字符串是以0结束指针加减操作时,考虑指针类型长度数组下标进行检查使用时sizeof或者strlen计算结构/字符串长度,避免手工计算规则6.2禁止内存泄漏。说明:内存和资源(包括定时器/文件句柄/Socket/队列/信号量/GUI等各种资源)泄漏是常见的错误。坚持下列措施可以避免内存泄漏:异常出口处检查内存、定时器/文件句柄/Socket/队列/信号量/GUI等资源是否全部释放。删除结构指针时,必须从底层向上层顺序删除。使用指针数组时,确保在释放数组时,数组中的每个元素指针是否己经提前被释放了。避免重复分配内存。小心使用有return break语句的宏,确保前面资源已经释放。检查队列中每个成员是否释放。规则6.3禁止引用已经释放的内存空间。说明:在实际编程过程中,稍不留心就会出现在一个模块中释放了某个内存块,而另一模块在随后的某个时刻又使用了它。示例:一个函数返回的局部自动存储对象的地址,导致引用已经释放的内存空间int* foobar (void)(int local_auto = 100;return &local_auto;坚持下列措施可以避免引用已经释放的内存空间:内存释放后,把指针置为NULL,使用内存指针前进行非空判断。耦合度较强的模块互相调用时,要仔细考虑其调用关系,防止已经删除的对象被再次使用。避免操作已发送消息的内存。规则6.4编程时,要防止差1错误。说明:此类错误一般是由于把“= 0) / 将出现下溢./ program code当size等于0时,再减不会小于0,而是OxFF,故程序是一个死循环。应如下修改。char size; / A unsigned char 改为 char while (size- = 0)./ program code7程序效率原则7.1在保证软件系统的正确性、简洁、可维护性、可靠性及可测性的前提下,提高代码效率。本章节后面所有规则和建议,都应在不影响前述可读性等质量属性的前提下实施。说明:不能一味地追求代码效率,而对软件的正确、简洁、可维护性、可靠性及可测性造成影响。记住:让一个正确的程序更快速,比让一个足够快的程序正确,要容易得太多。大多数时候,不要把注意力集中在如何使代码更快上,应首先关注让代码尽可能地清晰易读和更可靠。原则7.2通过对数据结构、程序算法的优化来提高效率。建议7.1将不变条件的计算移到循环体外。说明:将循环中与循环无关,不是每次循环都要做的操作,移到循环外部执行。示例一:for (int i = 0; i 10; i+ )sum += i;back_sum = sum;对于此for循环来说语句“back_Sum=sum;”没必要每次都执行,只需要执行一次即可,因此可以改为:for (int i = 0; i 10; i+ )(sum += i;back_sum = sum;示例二:for (_UL i = 0; i func_calc_max(); i+)/process;函数func_calc_max()没必要每次都执行,只需要执行一次即可,因此可以改为:_UL max = func_calc_max();for (_UL i = 0; i max; i+)/process;建议7.2对于多维大数组,避免来回跳跃式访问数组成员。示例:多维数组在内存中是从最后一维开始逐维展开连续存储的。下面这个对二维数组访问是以SIZE_B为步长跳跃访问,到尾部后再从头(第二个成员)开始,依此类推。局部性比较差,当步长较大时,可能造成cache不命中,反复从内存加载数据到cache。应该把i和j交换。for (int i = 0; i SIZE_B; i+)for(intj = 0;jSIZE_A; j+)(sum +=xji;建议7.3创建资源库,以减少分配对象的开销。说明:例如,使用线程池机制,避免线程频繁创建、销毁的系统调用;使用内存池,对于频繁申请、释放的小块内存,一次性申请一个大块的内存,当系统申请内存时,从内存池获取小块内存,使用完毕再释放到内存池中,避免内存申请释放的频繁系统调用。建议7.4将多次被调用的“小函数”改为inline函数或者宏实现。说明:如果编译器支持inline,可以采用inline函数。在做这种优化的时候一定要注意下面inline函数的优点:其一编译时不用展开,代码SIZE小。其二可以加断点,易于定位问题,例如对于引用计数加减的时候。其三函数编译时,编译器会做语法检查。8注释原则8.1优秀的代码可以自我解释,不通过注释即可轻易读懂。说明:优秀的代码不写注释也可轻易读懂,注释无法把糟糕的代码变好,需要很多注释来解释的代码往往存在坏味道,需要重构。示例:注释不能消除代码的坏味道:/*判断m是否为素数*/*返回值::是素数,:不是素数*/int p(int m)int k = sqrt(m);or (int i = 2; i k)retirrn 1 ;/* 遍历中没有发现整除的情况,返回*/elsereturn 0:重构代码后,不需要注释:int IsPrimeNumber(int num)int sqrt:_of_niim = sqi*T (num);for (int: i = 2; i =_num;(if (num % i = O)(re-turn FALSE ;Ietum TRUE ;原则8.2注释的内容要清楚、明了,含义准确,防止注释二义性。说明:有歧义的注释反而会导致维护者更难看懂代码,正如带两块表反而不知道准确时间。示例:注释与代码相矛盾,注释内容也不清楚,前后矛盾。/* 上报网管时要求故障ID与恢复ID才目一致*/*因此在此由告警级别获知是不是恢复ID */* 若是恢复工D则设置为CleaLrld,否则设置为Alarmld */if (CLEAR_ALARM_LEVEL != ReDara, level)
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 办公文档 > 解决方案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!