




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
华为技术C语言编程根底内部公开名目前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If标准临界资源爱护简洁既是美前言提高我司产品竞争力,研发要在以下几个方面下功夫:提高规划水平,把握正确的方向〔战略〕提高设计水平,搭建合理的系统〔战术〕提高编码水平,开发稳定的代码〔单兵作战技能〕前言我们为什么要进展培训?最好的医术是预防真正的难问题往往是低级错误引起的我们的编码水平不容乐观C是程序员的语言前言要提高编码水平,每个开发人员要做到:勤学苦练,提高编程技能前车之鉴,后世之师,不犯同样的错误;坚持代码Review、PC-LINT检查和单元测试;总而言之,就是少犯错误,尽早觉察错误名目前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If标准临界资源爱护简洁既是美根底篇之简洁就是美If(a&&b||c|d==e&f)这个表达式的正确运算挨次是什么?test(a++,++a,a++,++a,a++,++a)a=1;实际函数调用时,传入的参数值分别是多少?(++*p++)–(--*q--)语义是什么?a=b=1,c=2,d=3;e=4;a的值是多少?根底篇之简洁就是美这里没有答案,只有问题:我们问什么要写这样的代码?工作太轻松?BUG不够多?水平显不出?…………如何改进?优先级搞不清晰用括号;复合语句太罗嗦,拆成几行来写;套用两句广告词:把简洁的事情简单化,太累把简单的事情简洁化,奉献!根底篇之简洁就是美编码的三不原则不要挑战自己的记性不要挑战同事的急躁不要挑战编译器的水平编码的三用原则能用简洁语句的,就不要用简单的技巧能用成熟代码的,就不要再来一套能用上工具的,就肯定要机械化我们要求什么?structXXX{ charcA; shortsB; longlC;};voidmain{ char*pChar; pChar=(char*)malloc(7); memcpy(pChar,“abcdefgh“,sizeof(XXX)); printf(“%s\n“,pChar);
return;}我们要求什么?-续structXXX{ charcA; shortsB; longlC;};voidmain{ char*pChar; pChar=(char*)malloc(7);/*0,魔鬼数字;1,未申请成功怎么办?*/ memcpy(pChar,“abcdefgh”,sizeof(XXX));/*2,内存越界*/ printf(“%s\n”,pChar);/*3,没有字符串完毕符*/
return;/*4,没有释放内存*/}名目前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If标准临界资源爱护简洁既是美根底篇之sizeof数据构造是C语言的根底C语言的敏捷性很大程度上在于其数据构造的敏捷性要用好数据构造,首先要把握数据构造大小的计算系统为每个数据构造、每个变量都会安排一个对应的存储空间,这个存储空间的大小就是数据构造的尺寸根底篇之sizeoftypedefunionrecord{LONGlIndex;SHORTsLevel[6];CHARcPos;}REC_S;REC_S stMax,*pMax;CHAR
str[]=“Hello”;CHAR *pChar=str;ULONG ulGrade=10;USHORT usClass=10;DOUBLE dWeightUCHAR *pCharArray[10][10];Sizeof(stMax/pMax/str/pChar/ulGrade/usClass/dWeight/pCharArray)的取值分别是多少?根底篇之sizeoftypedefunionrecord{LONGlIndex;SHORTsLevel[6];CHARcPos;}REC_S;REC_S stMax〔12〕,*pMax〔4〕;CHAR str[]=“Hello”〔5+1=6,不要忘了\0〕;CHAR *pChar=str〔4〕;ULONG ulGrade=10〔4〕;USHORT usClass=10〔2〕;DOUBLE dWeight〔8〕;UCHAR *pCharArray[10][10]〔4×10×10=400〕;名目前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If标准临界资源爱护简洁既是美根底篇之字节对齐随着半导体技术的进展,我们经受8bit、16bit、32bit乃至64bit的CPU,我们产品当前大多使用32bitCPU从内存存取效率来说,4字节对齐的存取速度是最快的,非对齐状况下,CPU需要分解成两次32bit操作;缺省状况下,编译器自动对数据构造进展四字节对齐,以提高程序执行的效率,在特殊状况下,可以通过预编译指定指定数据构造为1字节对齐或者其他;对于PowerPC/Intel系列CPU,在非四字节对齐状况下,由CPU自动完成两次操作,对上层应用透亮;对于MIPSCPU,则需要通过编译选项进展干预,或者调整数据结果避开消失这种状况,否则会产生例外;字节对齐对数据构造的尺寸〔sizeof〕直接产生影响根底篇之字节对齐typedefstructHead{ CHARsrc[6]; ULONGulType; }HEAD_S; VOIDEncapsulation(CHAR*pBuf){ULONGulLen,ulDestIP;CHAR*pData=pBuf;ulLen=sizeof(HEAD_S);pData+=ulLen;ulDestIP=VOS_NTOHL((IP_S*)pData->ulDestIP);return;}根底篇之字节对齐#pragmapack(push)#pragmapack(1)typedefstructHead{ CHARsrc[6]; ULONGulType; }HEAD_S; #pragmapack(pop)VOIDEncapsulation(CHAR*pBuf){ULONGulLen,ulDestIP;CHAR*pData=pBuf;ulLen=sizeof(HEAD_S);pData+=len;ulDestIP=VOS_NTOHL((IP_S*)pData->ulDestIP);(MIPSCPU特别)return;}根底篇之字节对齐数据构造内部对齐,下面2种定义哪个好?typedefstructexample{USHORTusA;ULONGulA;USHORTusB;UCHARucA;USHORTusC;}EXAMPLE_SVStypedefstructexample{ULONGulA;USHORTusA;USHORTusB;USHORTusC;UCHARucA;UCHARucReserved;}EXAMPLE_S根底篇之字节对齐案例点评在定义数据构造时〔尤其是涉及协议和IPC通讯的时候〕,没有特殊理由的话,都定义成四字节对齐;这样做可能铺张几个字节,但是不会出问题;除了数据构造总长度是四字节对齐外,每一个局部也要保证它是四字节对齐的〔可以依据四字节、两字节、一字节的挨次排放数据构造中的各个域〕;对于无法定义成四字节对齐的数据构造,如以太网II、HDLC等,则将它们强行定义成一字节对齐,以躲避这个问题;对于MIPSCPU,在必需面对非四字节对齐状况时,承受编译选项方式加以解决;名目前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If标准临界资源爱护简洁既是美根底篇之字节序X86系统:VOIDQosConfigPolicy{ulDestIP=从命令行读取用户配置的参数;pQosPolicy->ulDestIP=ulDestIP;return;}主机处理:VOIDQosClassify{pIp=(IP_S*)pData;if(pIp->ulDestIp==pQosPolicy->ulDestIP){DoSomething;}return;}根底篇之字节序X86系统:VOIDQosConfigPolicy{ulDestIP=从命令行读取用户配置的参数;pQosPolicy->ulDestIP=ulDestIP;return;}主机处理:VOIDQosClassify{pIp=(IP_S*)pData;if(VOS_HTONL(pQosPolicy->ulDestIP)==pIp->ulDestIp){DoSomething;}return;}根底篇之字节序由于历史的缘由,业界存在两种字节序标准:BigEndian和LittleEndian,PowerPC是大头,X86是小头,有些CPU可以通过存放器设置支持不同的字节序,例如MIPS;所谓大头就是高位在低字节,低位在高字节;小头则与此相反,以0x345678为例,大头内存从低到高的存放次序为00,34,56,78,小头内存从低到高的存放次序为78,56,34,00;〔上面的数值统一为16进制表示形式〕字节序问题广泛存在于设备与设备之间、单板与单板之间、单板与底层芯片之间,只要两个处理单元的字节序不同,这个问题就存在,为了解决不同字节序的处理单元之间的通信问题,业界定义了主机序和网络序的概念,网络序主要用于信息传递,一般不用于计算,其字节挨次与大头全都;除了在编码时绷紧这根弦以外,我们在器件选择时尽量选择主机序与网络序全都的芯片,同一设备的不同单板使用一样的字节序,并优先选择支持大头的芯片,这样,即使不能彻底解决问题,也可以彻底躲避问题。名目前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If标准临界资源爱护简洁既是美根底篇之函数参数在C语言中,函数通过返回值和参数与调用者交换信息,对参数理解和使用的正确与否,直接影响到函数功能能否正确实现;函数参数自身占用的存储单元在堆栈中安排,入口参数指向的数值或者地址在函数入口处拷贝到堆栈区中,因此对函数参数所在存储单元的直接修改不会作用到函数之外,而对参数存储单元中存放的地址指向的存储空间的修改,则会在函数之外其作用;调用者在进展函数调用之前,必需事先申明被调用函数的原型,包括返回值类型和参数类型;根底篇之函数参数BOOLGetMemory(CHAR*p){/*申请内存*/p=(CHAR*)malloc(100);if(NULL==p){returnFALSE;}else{returnTRUE;}}VOIDTest(void){CHAR*str=NULL;If(GetMemory(str)){strcpy(str,“helloworld“);printf(str);}return;}根底篇之函数参数CHAR*GetMemory(CHAR**p){/*申请内存*/*p=(CHAR*)malloc(100);return*p;}VOIDTest(void){CHAR*str=NULL;If(NULL!=GetMemory(&str)){strcpy(str,“helloworld“);printf(str);free(str);str=NULL;}return;}名目前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If标准临界资源爱护简洁既是美根底篇之返回值在C语言中,函数的调用者通过返回值了解函数的执行状况;函数缺省的返回值类型为int,编程标准要求必需显示定义函数的返回类型;对于反映了函数执行状态的返回值,调用者必需依据返回值进展相应的处理,尤其是对于函数执行特别的情形;函数的出口参数能够起到与返回值类似的作用,上面一条规章对出口参数同样适用;对于函数返回值为恒值的函数,建议使用VOID类型的返回值;根底篇之返回值有什么问题?#include“stdlib.h“VOIDmain{CHAR*p;p=(CHAR*)malloc(100);VOS_Strcpy(p,“HelloWorld!\n”);printf(p);free(p);return;}根底篇之返回值#include“stdlib.h“VOIDmain{CHAR*p;p=(CHAR*)malloc(100);if(NULL!=p){strcpy(p,“HelloWorld!\n”);printf(p);free(p);}return;}根底篇之返回值LONGA{if(条件1){return;}returnVOS_OK;}VOIDB{if(A){DoSomeThing1;}else{DoSomeThing2;}return;}根底篇之返回值LONGA{if(条件1){returnVOS_ERROR;}returnVOS_OK;}VOIDB{if(A){DoSomeThing1;}else{DoSomeThing2;}return;}名目前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If标准临界资源爱护简洁既是美根底篇之强制类型转换强制类型转换给C语言编程带来了极大的敏捷性,也正是这种敏捷性,也埋下了很多的隐患;当目的构造的空间大于源构造的空间时,要重点关注内存访问超过源构造范围的情形,可能越界;当目的构造的空间小于源构造的空间时,要重点关注对目的构造赋值不能完全掩盖源构造范围的情形,可能遗漏;与构造体之间的强制类型转换相比,根本数据构造的强制类型转换更简洁消失上面描述的状况,使用的时候,肯定要慎之又慎;根底篇之类型转换——目的构造小于源构造VOIDB(CHAR*p){*p=1;return;}VOIDA{ULONGa;B((CHAR*)(&a));return;}a=?,是1吗?根底篇之类型转换——目的构造小于源构造VOIDB(CHAR*p){*p=1;return;}VOIDA{ULONGa;B((CHAR*)(&a));return;}a=?,是1吗?不行预知。根底篇之类型转换——目的构造大于源构造VOIDB(ULONG*p){*p=1000;return;}VOIDA{UCHARa=10;B((ULONG*)(&a));return;}在函数B给*p赋值之前,*p的值是多少?*p赋值之后,会消失什么样的情形?根底篇之类型转换——目的构造大于源构造VOIDB(ULONG*p){*p=1000;return;}VOIDA{UCHARa=10;B((ULONG*)(&a));return;}在函数B给*p赋值之前,*p的值是多少?不行预知*p赋值之后,会消失什么样的情形?越界名目前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If标准临界资源爱护简洁既是美根底篇之switch…caseC语言使用switch…case处理一个条件的多个取值有不同的处理分支的情形;当全部的case都匹配不成功时,进入default分支,编程标准要求switch…case必需显示设置default分支,假设程序从规律上不行能走到这个分支,可以在该分支中使用断言;完毕case分支的执行最常用的方法是使用break/return,否则程序将自动进入下一个case分支连续执行;编译器对switch…case可以做优化,用空间换取时间;default分支依据编程标准,要求放在switchcase的末尾,C语言本身不做强制要求;根底篇之switch…caseVOIDmain(){LONGulCnt1=0,ulCnt2=0;CHAR*ch=“aha!”;while(*ch){switch(*ch){case”a”:case”h”:ulCnt2++;default:ulCnt1++;}ch++;}printf(“%u,%u\n“,ulCnt1,ulCnt2);return;}ulCnt1和ulCnt2分别是多少?根底篇之switch…caseVOIDmain(){LONGulCnt1=0,ulCnt2=0;CHAR*ch=“aha!”;while(*ch){switch(*ch){case”a”:case”h”:ulCnt2++;default:ulCnt1++;}ch++;}printf(“%u,%u\n“,ulCnt1,ulCnt2);return;}ulCnt1=4ulCnt2=3名目前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If标准临界资源爱护简洁既是美根底篇之字符串ULONGBuildRun(CHAR**ppBuildrun){ULONGulLen;CHAR*pBuf;ulLen=CalculateBuildRunLen;if(0==ulLen){*ppBuildrun=NULL;returnB_ZERO_LENGTH;}pBuf=VOS_malloc(0,ulLen);if(NULL==pBuf){*ppBuildrun=NULL;returnB_MALLOC_FAILED;}VOS_StrCpy(pBuf,BuildRunInfo);*ppBuildrun=pBuf;returnVOS_OK;}根底篇之字符串ULONGBuildRun(CHAR**ppBuildrun){ULONGulLen;CHAR*pBuf;ulLen=CalculateBuildRunLen;if(0==ulLen){*ppBuildrun=NULL;returnB_ZERO_LENGTH;}pBuf=VOS_malloc(0,ulLen+1);if(NULL==pBuf){*ppBuildrun=NULL;returnB_MALLOC_FAILED;}VOS_StrCpy(pBuf,BuildRunInfo);*ppBuildrun=pBuf;returnVOS_OK;}根底篇之字符串案例点评:作为信息输出,字符串必不行少;字符串在动态申请时少安排一个字符是特别普遍的一个错误;strlen等计算字符串长度的函数都是不考虑字符串的\0完毕符的;代码Review时,字符串越界问题是一个大客户,要盯紧看严;根底篇之字符串〔续〕再看一个例子:LONGGetXYZHead〔CHAR**pData,CHAR**pBuf){ULONGulLen;CHAR*pTmpData=*pData,*pTmpBuf=*pBuf;ulLen=AnalysisHead(pTmpBuf);/*strcpy(pTmpData,pTmpBuf);*//*sprintf(pTmpData,“%s”,pTmpBuf);*//*memcpy(pTmpData,pTmpBuf,ulLen);*/returnulLen;}*pBuf中存放是是XYZ协议的Peer发送过来的一段报文,这个函数负责将协议头拷贝到pData指向的空间中;假设空间是足够的,准备选择哪条语句;根底篇之字符串〔续〕LONGGetXYZHead〔CHAR**pData,CHAR**pBuf){ULONGulLen;CHAR*pTmpData=*pData,*pTmpBuf=*pBuf;ulLen=AnalysisHead(pTmpBuf);/*strcpy(pTmpData,pTmpBuf);*//*sprintf(pTmpData,“%s”,pTmpBuf);*/memcpy(pTmpData,pTmpBuf,ulLen);returnulLen;}使用memcpy,由于没有人保证协议头中不消失’\0’,而且协议头特别简洁消失这个值,这个时候它就不再是字符串,字符串工具函数必需是专款专用,而memcpy则要广泛得多;根底篇之字符串〔再续〕VOIDGetDigitString〔CHAR*pData,CHAR*pBuf){CHAR*pTmpData=pData,*pTmpBuf=pBuf;while(‘\0’!=(*pTmpBuf)){if((‘0’<=*pTmpBuf)&&(‘9’>=*pTmpBuf)){*pTmpData=*pTmpBuf;pTmpData++;}else{break;}pTmpBuf++;}return;}该函数的功能是将pBuf中的连续数字拷贝到pData中生成一个新的字符串根底篇之字符串〔再续〕VOIDGetDigitString〔CHAR*pData,CHAR*pBuf){CHAR*pTmpData=pData,*pTmpBuf=pBuf;while(‘\0’!=(*pTmpBuf)){if((‘0’<=*pTmpBuf)&&(‘9’>=*pTmpBuf)){*pTmpData=*pTmpBuf;pTmpData++;}else{break;}pTmpBuf++;}*pTmpData=‘\0’;/*没有尾字符,就不是字符串*/return;}名目前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If标准临界资源爱护简洁既是美根底篇之溢出#defineDEFAULT_EXPIRE_TIME300000/*5分钟*/VOIDARPRecordExpireTime(ARP_Entry_S*pArpEntry){/*计算表项估计老化时的时间,以系统启动以来的毫秒数表示*/pARPEntry->ulExpireTime=GetBootTime+DEFAULT_EXPIRE_TIME;return;}VOID*ARPExpire(ARP_Entry_S*pArpEntry){ARP_Entry_s*pArpNext;while(pArpEntry){if(GetBootTime<pArpEntry->ulExpireTime){break;}pArpNext=pArpEntry->pNext;Free(pArpEntry);pArpEntry=pArpNext;}return(VOID*)pArpEntry;}根底篇之溢出#defineDEFAULT_EXPIRE_TIME300000/*5分钟*/VOIDARPRecordExpireTime(ARP_Entry_S*pArpEntry){/*计算表项估计老化时的时间,以系统启动以来的毫秒数表示*/pARPEntry->ulExpireTime=GetBootTime+DEFAULT_EXPIRE_TIME;return;}VOID*ARPExpire(ARP_Entry_S*pArpEntry){ARP_Entry_s*pArpNext;while(pArpEntry){if(GetBootTime<pArpEntry->ulExpireTime)/*ULONG溢出如何处理?包括ExpireTime溢出、GetBootTime溢出*//*解决方案作为思考题*/{break;}pArpNext=pArpEntry->pNext;Free(pArpEntry);pArpEntry=pArpNext;}return(VOID*)pArpEntry;}根底篇之溢出案例点评:在我们的系统中,溢出通常消失在时间处理上;系统时钟一般使用两个ULONG表示时间,准确到毫秒;上层软件使用时间时一般无视掉高位,只保存低32位。对于LONG的状况,25天后翻转;对于ULONG的状况,49天后翻转;假设没有特殊的需要,建议使用系统供给的准确到秒的32位时钟,在LONG状况下60年翻转,根本可以不考虑这件事情;假设肯定要使用毫秒钟,就需要考虑时钟翻转的状况;根底篇之溢出〔续〕ULONGSequenceAdd(ULONGulCount){ULONGulSum=0;while(0<=ulCount){ulSum+=ulCount;ulCount--;}returnulSum;} 根底篇之溢出〔续〕ULONGSequenceAdd(ULONGulCount){ULONGulSum=0;while(0<=ulCount)/*条件永久为真,死循环*/{ulSum+=ulCount;ulCount--;}returnulSum;} 根底篇之溢出〔续二〕VOIDShowLong(ULONGulCount){CHARstInfo[16];VOS_Sprintf(stInfo,“%ld\n\r”,ulCount);Printf(stInfo);return;} 根底篇之溢出〔续二〕VOIDShowLong(ULONGulCount){CHARstInfo[16];VOS_Sprintf(stInfo,“%lu\n\r”,
ulCount);Printf(stInfo);return;} 在显示无符号整数时,使用正确的%描述符根底篇之溢出〔续〕案例点评:要解决溢出问题,首先要明确数据构造的取值范围;无符号数和有符号数在取值范围上的差异,也简洁引起溢出;假设非特殊需要,不要进展有符号数和无符号数的强制类型转换,以免产生不必要的麻烦;假设非特殊需要,不要进展从(U)LONG到(U)SHORT到(U)char的转换,以免产生不必要的麻烦;名目前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If标准临界资源爱护简洁既是美根底篇之资源释放VOIDPrintDigit(ULONGulData){CHAR*pBuf;pBuf=(CHAR*)malloc(16);if(NULL==pBuf){returnNULL;}VOS_Sprintf(pBuf,”%lu\n\r”,ulData);printf(pBuf);return;}根底篇之资源释放VOIDPrintDigit(ULONGulData){CHAR*pBuf;pBuf=(CHAR*)malloc(16);if(NULL==pBuf){returnNULL;}VOS_Sprintf(pBuf,”%lu\n\r”,ulData);printf(pBuf);Free(pBuf);/*Review九句箴言:观察Malloc找Free!*/return;}根底篇之资源释放(续〕Node_Head_S*CreateNode(ULONGulNType){Node_Head_S*pNode;Node_Body_S*pBody;pNode=(Node_Head_S*)malloc(sizeof(Node_Head_S));if(NULL==pNode){returnNULL;}pBody=(Node_Body_S*)malloc(sizeof(Node_Body_S));if(NULL==pBody){returnNULL;}pNode->pBody=pBody;pNode->ulNType=ulNType;returnpNode;}根底篇之资源释放(续〕Node_Head_S*CreateNode(ULONGulNType){Node_Head_S*pNode;Node_Body_S*pBody;pNode=(Node_Head_S*)malloc(sizeof(Node_Head_S));if(NULL==pNode){returnNULL;}pBody=(Node_Body_S*)malloc(sizeof(Node_Body_S));if(NULL==pBody){Free(pNode);/*特别分支最简洁遗忘清扫战场,顾头也要顾尾*/returnNULL;}pNode->pBody=pBody;pNode->ulNType=ulNType;returnpNode;}根底篇之资源释放案例点评资源泄漏是代码Review中最常见的错误之一申请的每个资源必需明确由谁负责释放,何时释放,在何处释放;在特别分支中,保持糊涂的头脑,清理战场;在特定功能去使能时,需要完成的主要工作就是资源清退;名目前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If标准临界资源爱护简洁既是美根底篇之if标准LONGIsZero(ULONGulCnt){if(ulCnt==0)
{returnW_ZERO;
}else{returnW_NONZERO;}}函数的功能为:参数为0时返回W_ZERO;否则返回W_NOZERO;根底篇之if标准LONGIsZero(ULONGulCnt){if(0==ulCnt){returnW_ZERO;}else{returnW_NONZERO;}}编程标准反复强调变量放在双等号的右边,常量放在左边,就是为了躲避消失If(ulCnt=0)这种语法正确,但是极有可能是笔误的状况。为了杜绝这种不必要的规律问题,要求必需严格遵守编程标准。根底篇之if标准〔续〕If(ulCnt=ulData){}VsulCnt=ulData;If(ulCnt){}VsIf(ulCnt==ulData){}上面的语句语法上都是正确的,但写法哪个好?根底篇之if标准〔续〕If(ulCnt=ulData){}VsulCnt=ulData;If(ulCnt){}VsIf(ulCnt==ulData){}第一种和第三种特别简洁消失笔误,为了杜绝不必要的问题,不要使用第一种方式编写程序,而用方式二替代;根底篇之if标准〔再续〕VOIDTest{if(Func_A&&Func_B){DoSomething_A;}else{DoSomething_B;}return;}在任何状况下是否语义都是正确的?根底篇之if标准〔再续〕VOIDTestVOIDTest{{ULONGulRet1,ulRet2;if(Func_A){{ulRet1=Func_A;{ulRet2=Func_B;if(Func_B)if(ulRet1&&ulRet2)DoSomething_A;DoSomething_A;}}elseelse{{DoSomething_B;DoSomething_B;}}}return;else}{DoSomething_B;}return;}假设程序规律为Func_A的返回值为假的状况下,不执行Func_B,则上一页的程序是正确的,但是要求承受本页右侧的程序模式实现;假设Func_A和Func_B都无条件执行,再依据综合结果,打算走哪个分支,则使用本页左侧的程序;为了明确程序规律,同时要求使用注释加以说明,以便利后期的维护根底篇之if标准〔续三〕VOS_Assert(Func_A)vsVOS_DBGASSERT(Func_A)这两个用法有什么区分?VOS_Aseert用法保证在任何状况下Func_A都得到执行;VOS_DBGASSERT则与系统是翻开release宏还是debug宏相关:当系统翻开了debug宏时,起语义与方式1完全一样;当系统翻开的是release宏,则VOS_DBGASSERT在编译时将被无视,Func_A自然页得不到运行;使用VOS_DBGASSERT的时候要慎重,要清晰了解不同系统宏下的不同语义,要保证两种场景下,程序规律都是正确的;为了避开不必要的麻烦,要求不允许在VOS_DBGASSERT中使用函数!根底篇之if标准〔续四〕LONGIsA(CHARch){if((‘a’!=ch)||(‘A’!=ch)){returnVOS_ERROR;}else{returnVOS_OK;}}函数功能为推断输入的字符是否是’a’或者’A’,假设是,则返回VOS_OK,否则返回VOS_ERROR根底篇之if标准〔续四〕LONGIsA(CHARch){if((‘a’!=ch)||(‘A’!=ch))/*规律恒为真,规律错误,笔误?*/{returnVOS_ERROR;}else{returnVOS_OK;}}PC-LINT可以检查出规律恒为真或者假的规律表达式,根本都是我们预期之外的规律,PC-LINT确实是一个好东西。名目前言sizeof字节对齐字节序函数参数返回值强制类型转换Switchcase字符串溢出资源释放If标准临界资源爱护简洁既是美根底篇之临界资源爱护VOIDSendMBuf(MBUF_S*pMBuf){空闲BD数=DRV_GetFreeBD;报文片数=MBUF_GetFrag(pMBuf);if(报文片数>空闲BD数〕{return;/*发送拥塞,临时缓存*/}intr_lock;CopyMBufIntoBD;空闲BD数-=报文片数;intr_unlock;}TaskSOCK:
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 婚姻中的财产安全协议3篇
- 工作绩效承包2篇
- 产品委托生产授权协议范本2篇
- 工程质量保证书版示例
- 地下车库销售合同样本3篇
- 家用玻璃花瓶定制协议3篇
- 乳制品包装材料选购3篇
- 冷库转让合同模板3篇
- 燃气具产品可靠性分析考核试卷
- 纤维板行业发展趋势与市场预测考核试卷
- 电台项目可行性研究报告
- 2025年度事业单位招聘考试公共基础知识仿真模拟试卷及答案(共五套)
- 2025年广西壮族自治区南宁市中考一模生物试题(含答案)
- 长江流域大水面生态渔业的发展现状与发展潜力分析
- SQLSERVER如何配置内存提高性能配置方案
- 电视台影视拍摄合同协议
- 装配式建筑技术创新与可持续发展-全面剖析
- 装饰公司结算管理制度
- 实习生顶岗实习安全教育
- 网络灾难恢复计划试题及答案
- 物业五一节前安全教育
评论
0/150
提交评论