版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
希望对大家有所帮助.名谢您的浏览!希望对大家有所帮助.名谢您的浏览!#/13目录简单就是美2・sizeof字节序函数参数返回值强制类型转换7・swithcase字符串资源释放辻规范临界资源保护1.简单就是美优先级搞不淸楚用括号复合语句太罗嗦,拆成几行来写编码的三不原则不要挑战自己的记性不要挑战自己的耐心不要挑战编译器的水平编码的三用原则能用简单句的,就不要用复杂的技巧能用成熟代码的,就不要再来一套能用上工具的,就一泄要机械化Structxxx{charcA;shortsB;long1C;}voidmainO{char *pchar;pchar=(char*)malloc(7); /* 1—魔鬼的数字:2—申请失败后怎么办?mencpy(pchar,°abcdefghM,sizefo(xxx)); /* 3—内存*/printf(“$s\n",pchar); /*缺少字符串结束符必越界*/return; /*5—退岀前没有释放内存*/}2・sizeof数据结构是C语言的基础。C语言的灵活性很大,程度上在于英数搦结构的灵活性。要用好的数据结构,首先要掌握数据结构的大小的计算,系统的每个数据机构,每个变量都会分配到一个对应的存储空间,这个存储空间的大小就是数据结构的尺寸。sizeof为编译时的一元运算符,可用来讣算任一对彖的大小sizeof的结果是编译时的常量sizeof不能用于函数类型,不完全类型或位字段。不完全类型指具有未知存储大小的数据类型。如未知存储大小的数组类型,未知内容的结构或联合类型,void类型等。字节序X86系统voidQosConfigPolicy(xxx){ulDestIP二从命令行读取用户配置的参数;pQosPoliscy->ulDestIP=ulDestIP;return;}主机处理voidQosClassify(xxx){Pip=(IP-S*)pData;If(pQosPolicy->ulDestIP二二plp->ulDestIP){Vos_HTONL(pQosPolicy->ulDestIP;DoSomethingO;}Return;}由于历史的原因,世界存在两种字节序标准 BigEndian和LittleEndian。PowerPC是大头,X86是小头。有些CPU可以通过寄存器设置支持不同的字节序。如MIPSBigEndian一一高位在低字节,地位在高字节LittleEndian一一低位在低字节,高位在高字节e.g.0x345678大头内存从低到高存放次序00,34,56,78:小头内存从低到高存放次序7&56,34,00字节序问题广泛存在于设备与设备之间,单板与单板之间,单板与底层之间,只要两个处理单元的字节序不同,这个问题就存在。为了解决不同字节序的处理单元之间的同信问题,世界上泄义了主机序和网络序的概念,网络序主要用于信息传递,一般不用于计算,其字节顺序与大头一致。除在编码时紧绷这根弦之外,我们在器件选择是主机序与网络序一致的芯片,同一设备的不同单板使用相同的字节序。并优先选择支持大头的芯片,这样即使不能彻底解决问题,也可以彻底规避问题。函数参数C语言中,函数通过返回值和参数与调用者交换信息。函数参数自身占用的存储单元在堆栈中分配。入口参数指向的数组或地址,在函数入口处拷贝到堆栈区中,因此对函数参数所在存储单元的直接修改不会作用到函数之外,而对参数存储单元中存放的地址指向的存储空间的修改,则会在函数之外起作用。调用者在进行函数调用之前,必须事先申明被调用函数的原型,包括返回值类型和参数类型。CHAR*GetMemory(CHAR*p)/*申请内存*/P=(CHAR*)malloc(100);Returnp;}Malloc申请的内存空间与操作系统有关,在PC中molloc申请空间以byte为单位,如申请100个int内存则p=(INT*)malloc(400);VOIDTest(void){CHAR*str二NULL;If(NULL!=GetMemory(&str)){Strcpy(str,”hellworldM);Print(str);Free(str);Str=NULL;Return;}返回值C语言中,函数的调用者通过返回值了解函数的执行情况,函数缺省的返回值类型为int,编程规范要求必须显示左义函数的返回类型。对于反映了函数执行状态的返回值,调用者必须依据返回值进行相应的处理,尤其是对于函数执行异常的情形。函数的出口参数能够起到与返回值类似的作用,上一条同样适用于出口参数。对于函数返回值为恒值得函数,建议使用void返回值^include"stdio.h”VoidmainO{Char*p;P=(char*)malloc(100);If(p!=NULL){Strep(p,”helloworld!\nf?);Printf(p);Free(p);}Return;}LongA(){If(expO){ReturnVOS_ERROR;}RuturnVOS.OK;}LongB()If(AO){Dosomethingl();}else{Dosomething2();}Return;}强制类型转换强制类型转换给C编程带来了极大灵活性,也正是这种灵活性,埋下了无数隐想。当目地结构的空间大于源结构的空间时,要重点关注内存访问超过源结构范用的情况,可能越界。当目地结构的空间小于源结构空间时,要重点关注对目地结构赋值不能完全覆盖源结构范围的情形,能遗漏。与结构体之间的强制类型转换相比,基本数据的强制类型转换更容易出现上述情况目地结构小于源结构VoidB(char*p){*p=1;Return;}VoidAO{Ulonga;B((char*)(&a));Return;}A二?是1吗?答案:不可预知目的结构大于源结构VoidB(ulong*p){*p=1000;Return;}VoidAO{Uchara=10;B((ulong*)(&a));Return;}在函数B给*戸赋值前,*P值时多少?答案:不可预知柑赋值后,会出现什么情况?答案:越界switchcaseC语言使用switchcase处理一个条件的多个取值有不同的处理分支的情况。当所有的case都匹配不成功时,进入default分支。如果程序从逻辑上不可能上到这个分支,可以在该分支中使用断言。结束case分支的执行最常用的办法是使用break/return,否则程序将自动进入F—个case分支继续执行。编译器对switch..case可以做优化,用空间换取时间,default分支按照编程规范,要求放在switchcase的末尾,C本身不做强制要求。VoidmainO{Longulcntl=0,ulcnt2=0;Char*ch=44aha!”;While(*ch){Switch(*ch){Case :Case :ulcnt2++;Default:Ulcntl++;}Ch++;}Printf(“%u,%u\n”,ulcntl,ulcnt2);Return;}Ulcntl和ulcnt2分别是多少?Ulcntl=4,ulcnt2=3字符串Ulongbuildrun((char**ppbuildrun){Ulongullen;Char*pbuf;Ullen=calculatebuildrunlenO;If(0==ulen){*ppbuildrun=NULL;ReturnB_ZER0_LE7GTH;}Pbuf=V0S_malloc(0,ullen);If(NULL=pbuf){*ppbuildrun=NULL;ReturnB.MALLOC.FAILED;VOS_Strcpy(pbuftbuildruninfo);*ppbuildrun=pbuf;ReturnVOS.OK;}案例点评:为信息输岀,字符串必不可少,字符串在动态申请时少分配一个字符是非常普遍的一个错误,strlen等计算字符串长度的函数都是不考虑字符串的\0结束符的,代码review时,字符串越界问题是一个大客户,要盯紧看严Sizeof与strlen的区别Charchar.]="abc”;sizeof(char)=4,strlen(char)=3Charchar1]=°ab\0c,?;sizeof(char)=5,strlen(char)=2Sizeof()为编译时执行,strlen0为运行时执行Longgetxyhead(char**pdata,char**pbuf){Ulongulen;Char*ptmpdata=*pdata,*ptmbuf=*pbuf;Ullen=analysisheand(ptmpbuf);//strcpy(ptmpdata,ptmpbuf);//sprintf(ptmpdata,ptmpbuf,ullen);//memcpy(ptmpdata,ptmpbuf,ullen);Returnullen;}*pbuf中存放的是xyz协议的peer发送过来的一段报文,这个函数负责将协议头拷贝到pdata指向的空间中,假定空间是够,那条语句最合适?Mencpy语句最合适因为没人保证*pbuf中不岀现'\0',infact,协议头中非常容易出现’\0',此时它不再是字符串,字符串工具函数必须是专款专用,而mencpy则要宽泛得多。VoidgetdigitString(char*pdata,char*pbuf){Char*ptmpdata=pdata,*ptmpbuf=pbuf;Wh订e( '\0‘ !=(*ptmpbuf)){If((‘0’ <=*ptmpbuf)&&(‘9’ >=*ptmpbuf)){*ptmpdata=*ptmpbuf;Ptmpdata++;}Else{Break;}Ptmpbuf++;}*ptmpdata二'\0'; /*没有'\0',就不是字符串*/Return;}该函数功能是将pbuf中的连续数字拷贝到pdata中,生成一个新徳字符串!^defineBUFFER.SIZE250VoidTest(void){Charpszbuf[BUFFER_SIZE]二”\0”;Snprintf(pszbuf,sizeof(pszbuf)-l,”file:%sline:%sM,_FILE_,_LINE_);Pszbuf[sizeof(pszbuf)-1]= "\0‘;Printf(“%s”,pszbuf);Return;}#defineBUFFER.SIZE250VoidTest(char*pszmsg){Char*pszbuf=NULL;If(NULL==pszmsg)Return;Pszbuf=malloc(BUFFER_SIZE+l);If(pszbuf!=NULL){Strncpy(pszbuf,pszmsg,BUFFER_SIZE);Pszbuf[BUFFER.SIZE]二'\0‘;Free(pszbuf);}Return;}案例点评C语言提供的函数库字符串函数sprintf/vsprintf/strcpy/strcat/gets等非常危险,很容易导致内存越界,应使用安全的字符串库函数snprintf/strncpy/strncat/fgets指定操作内存大小。Strncpy等安全函数,当拷贝字符串到达指左的长度时,不会在目标字符串结尾添加'\0‘,必须手工添加’\0‘,可以在调用strncpy后紧接着赋0,也可以在申请内存时将最后一字节置0。可以使用Dopra提供的改进的安全函数V0S_strncpy自动在目标字符串结尾添加'\0',但要注意,此时拷贝的字符串字节数比标准C库的strncpy少了一个字节。注意Dopra提供的V0S_strncpy的实现与标准C库一致,不会自动添加’\0'。函数功能:把190个字节空间中能容纳的非负整数按小到大的顺序不间断打印出来。#defineBUFFER.SIZE190Voidmain(void){CharszbuftBUFFER.SIZE]={0};Inti=0;For(;i<100;i++) /*190个字节空间最多能容纳多少个整数?100?*/{Sprintf(szbuf+strlen(szbuf), ,i);}Printf(u%s\n,?,szbuf);Return;}当i>二10时,每个整数占用两字节,循环100次后,Buffer总长度(包括’\0')会超过190,导致内存写越界。案例点评上述例子属于人工计算字符串长度岀错的典型例子,案例中100就是人工计算的魔鬼数字。魔鬼数字是指代码中出现的难以理解的数字。这里的代码不仅仅指*.c文件,也包含宋定义。简单的使用宏替换魔鬼数字并没用消失,正确的做法,除使用宏表明数字的含义外,还应从若干基础数字自动运算岀衍生数字,任何情况下都不要手工计算数字!计算数字的工作应由计算机完成。#defineBUFFER.SIZE190Voidmain(void){CharszbufEBUFFER.SIZE]={0};inti=0;intiposition=0; /*记录每次copy的起始位置*/intlength=0; /*记录每次copy的字符数(不算’\0')*/for(;;i++){Length=snprintf(snbuf+iposition,(BUFFER_SIZET)-iposition,%d",i);If(length<=0) /*如果length<=0,说明到达了缓冲区末尾,跳出循环!*/{Szbuf[iposition]= "\0‘;Break;}Iposition+二length;}Printf(11%s\n”,szbuf);Return;}资源释放Voidprintdigit(ulonguldata){Char*pbuf;Pbuf=(char*)malloc(16);If(NULL=pbuf){ReturnNULL;}V0S_sprintf(pbuf,U%lu\n\rM,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(pnode=NULL){ReturnNULL;}pbody=(Node_body_s*)malloc(sizeof(Node_body_s));If(pbody=NULL){Free(pnode); /*异常分支最容易忘记打扫战场,顾头也要顾尾*/ReturnNULL;}Pnode->pbody=pbody;Pnode->ulntype=ulntype;Returnpnode;}案例点评资源泄履是代码review中最常见的错误之一,申请的每个资源必须明确由谁负责释放,何时何处释放。在异常分支中,保持头脑淸醒,淸理战场。在特左功能去使能时,需要完成的主要工作就是资源淸退。if规范Longlszero(ulongulcnt){If(ulcnt=0){ReturnW_ZERO;}Else{ReturnW.NONZERO;}}函数功能:参数为0返回W_ZERO,否则返回W_NONZERO编程规范反复强调变量存放在=右边,常量放在左边,是为了规避出现辻(ulcnt二0)这种语法正确,但极有可能是笔误的情况。If(ulcnt=uldata) if(ulcnt=uldata) ulcnt=uldata;{ VS・ { VS. if(ulcnt)}}{}上面三种语句语法都正确,那种最好。第一种和第二种非常容易岀现笔误,为了杜绝不不要的问题,不要使用第一种,二用第三种代替。VoidTest(){If(Func.AO&&Func.B0){Dosomething_A();}Else{Dosomething_B();}Return;}上面程序在任何情况下是否语义都是正确的?voidTest0{Ulongulretl,uiret2;Ulretl=Func_A();Ulret2=Fucn_B();If(ulretl&&ulret2){Dosomething_A();}Else{Dosomething_B();}Return;}2)VoidTest0{If(Func.AO){If(Func_B0){Dosomething_A();}Else
Dosomething_B();}}Else{Dosomething_B();Return;}如果程序逻辑为Func_A()的返回值为假的情况下不执行Func_B(),则上页程序是正确的,但要求用2)的程序模式来实现。如果Func_A和Func_B都无条件执行,再根据综合结果决定定哪个分支,则使用程序1)。为了明确程序逻辑,同时要求注释加以说明,以便后期维护。VOS.Assert(Func.AO)VS.VOS.DBGASSERT(Func.AO)这两个用法有什么区别?VOS_Assert用法保证任何情况下Func_A都得到执行,VOS_DBGASSERT则与系统是打开release宏还是debug宏有关。当系统打开release宏,则VOS_DBGASSERT在编译时将被忽略,Func_A0得不到执行。使用VOS_DBGASSERT时要谨慎,要淸楚了解不同系统宏的不同语义,要保证两种场景下,程序逻辑都是正确的。为了避免不必要的麻烦,要求禁止在VOS.DBGASSERT中使用函数。LongIsA(charch){If(('a' !=ch)('A' !=ch))/*逻借恒为真,逻辑错误?笔误?*/{ReturnVOS_ERROR;}Else{ReturnVOS.OK;}}函数功能:判断输入字符是否是W或 如果是,则返回VOS.OKo否则返回VOS_ERROR°PC-LINT可以检査出逻辑恒为真或假的逻辑表达式基本都是我们预期之外的逻辑。11•临界资源保护Voidsendmbuf(mbuf_s*pmbuf)/*彻底保护*//*彻底保护*//*打扫战场*//*发送拥塞,暂时缓存*/空闲BD数二DRV.GetFreeBDO;报文片数=mbuf_GetFrag(pmbuf);If(报文片数>空闲BD数){Intr_unlock0;Return(QOS_CONGEST);}CopymbufintoBDO;空闲BD数-二报文片数:
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 中医护理的推拿疗法
- 鼓胀护理并发症预防与处理
- 房地产市场营销策略与技巧指南
- 家庭教育中的学习能力培养作业指导书
- 采购订单逾期催办函3篇范本
- 汽车维护服务操作流程手册
- 2026年农艺师招聘笔试重点难点解析
- 2026年证券从业金融市场仿真题及模拟题集
- 2026年法律职业资格考试模拟练习
- 2026年医学胃部知识讲座
- 安宁疗护获奖课件
- QB∕T 8045-2024 聚对苯二甲酸乙二醇酯(PET)结构泡沫板材
- 五金购销合同清单
- 冀东民俗文化英汉平行语料库的构建与应用
- RTK道路放样培训
- 儿童康复护理小讲课课件
- 高大模板监理细则
- 辽统监表A-1 工程开工复工报审表
- 现代控制理论总复习
- 第十章食品添加剂
- 毕业设计-贯通测量方案设计
评论
0/150
提交评论