华为技术有限司C语言编程基础ppt课件.ppt

上传人:牧羊曲112 文档编号:1405467 上传时间:2022-11-20 格式:PPT 页数:86 大小:1.12MB
返回 下载 相关 举报
华为技术有限司C语言编程基础ppt课件.ppt_第1页
第1页 / 共86页
华为技术有限司C语言编程基础ppt课件.ppt_第2页
第2页 / 共86页
华为技术有限司C语言编程基础ppt课件.ppt_第3页
第3页 / 共86页
华为技术有限司C语言编程基础ppt课件.ppt_第4页
第4页 / 共86页
华为技术有限司C语言编程基础ppt课件.ppt_第5页
第5页 / 共86页
点击查看更多>>
资源描述

《华为技术有限司C语言编程基础ppt课件.ppt》由会员分享,可在线阅读,更多相关《华为技术有限司C语言编程基础ppt课件.ppt(86页珍藏版)》请在三一办公上搜索。

1、,华为技术有限公司C语言编程基础,内部公开,目录,前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美,前言,提高我司产品竞争力,研发要在以下几个方面下功夫:提高规划水平,把握正确的方向(战略)提高设计水平,搭建合理的系统(战术)提高编码水平,开发稳定的代码(单兵作战技能),前言,我们为什么要进行培训?最好的医术是预防真正的难问题往往是低级错误引起的我们的编码水平不容乐观C是程序员的语言,前言,要提高编码水平,每个开发人员要做到:勤学苦练,提高编程技能前车之鉴,后世之师,不犯同样的错误;坚持代码Review、PC-LIN

2、T检查和单元测试;总而言之,就是少犯错误,尽早发现错误,目录,前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美,基础篇之简单就是美,If (a a的值是多少?,基础篇之简单就是美,这里没有答案,只有问题:我们问什么要写这样的代码?工作太轻松?BUG不够多?水平显不出?如何改进?优先级搞不清楚用括号;复合语句太罗嗦,拆成几行来写;套用两句广告词:把简单的事情复杂化,太累把复杂的事情简单化,贡献!,基础篇之简单就是美,编码的三不原则不要挑战自己的记性不要挑战同事的耐心不要挑战编译器的水平编码的三用原则能用简单语句的,就不

3、要用复杂的技巧能用成熟代码的,就不要再来一套能用上工具的,就一定要机械化,我们要求什么?,struct XXXchar cA;short sB;long lC;void main()char *pChar;pChar = (char *)malloc(7);memcpy(pChar, abcdefgh, sizeof(XXX);printf(%sn, pChar); return;,我们要求什么?续,struct XXXchar cA;short sB;long lC;void main()char *pChar;pChar = (char *)malloc(7); /*0,魔鬼数字; 1,未

4、申请成功怎么办?*/memcpy(pChar, “abcdefgh”, sizeof(XXX); /*2,内存越界*/printf(“%sn”, pChar); /*3,没有字符串结束符*/ return; /*4,没有释放内存*/,目录,前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美,基础篇之sizeof,数据结构是C语言的基础C语言的灵活性很大程度上在于其数据结构的灵活性要用好数据结构,首先要掌握数据结构大小的计算系统为每个数据结构、每个变量都会分配一个对应的存储空间,这个存储空间的大小就是数据结构的尺寸,基础

5、篇之sizeof,typedef union record LONG lIndex; SHORT sLevel6; CHAR cPos; REC_S;REC_SstMax,*pMax;CHARstr = “Hello” ;CHAR*pChar = str ;ULONGulGrade = 10;USHORTusClass 10;DOUBLEdWeightUCHAR*pCharArray1010;Sizeof(stMax/pMax/str/pChar/ulGrade/usClass/dWeight/pCharArray)的取值分别是多少?,基础篇之sizeof,typedef union reco

6、rd LONG lIndex; SHORT sLevel6; CHAR cPos; REC_S;REC_SstMax(12),*pMax(4);CHARstr = “Hello”(516,不要忘了0) ;CHAR*pChar = str (4);ULONGulGrade = 10(4);USHORTusClass 10(2);DOUBLEdWeight(8);UCHAR*pCharArray1010(41010400);,目录,前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美,基础篇之字节对齐,随着半导体技术的发展,

7、我们经历8bit、16bit、32bit乃至64bit的CPU,我们产品当前大多使用32bit CPU从内存存取效率来说,4字节对齐的存取速度是最快的,非对齐情况下,CPU需要分解成两次32bit操作;缺省情况下,编译器自动对数据结构进行四字节对齐,以提高程序执行的效率,在特殊情况下,可以通过预编译指定指定数据结构为1字节对齐或者其他;对于Power PC/Intel系列CPU,在非四字节对齐情况下,由CPU自动完成两次操作,对上层应用透明;对于MIPS CPU,则需要通过编译选项进行干预,或者调整数据结果避免出现这种情况,否则会产生例外;字节对齐对数据结构的尺寸(sizeof)直接产生影响,

8、基础篇之字节对齐,typedef struct Head CHAR src 6; ULONG ulType; HEAD_S;VOID Encapsulation(CHAR* pBuf) ULONG ulLen, ulDestIP; CHAR* pData = pBuf; ulLen = sizeof(HEAD_S); pData += ulLen; ulDestIP = VOS_NTOHL(IP_S *)pData-ulDestIP); return;,基础篇之字节对齐,#pragma pack(push)#pragma pack(1)typedef struct Head CHAR src

9、6; ULONG ulType; HEAD_S;#pragma pack(pop)VOID Encapsulation(CHAR* pBuf) ULONG ulLen, ulDestIP; CHAR* pData = pBuf; ulLen = sizeof(HEAD_S); pData += len; ulDestIP = VOS_NTOHL(IP_S *)pData-ulDestIP); (MIPS CPU 异常) return;,基础篇之字节对齐,数据结构内部对齐,下面2种定义哪个好?typedef struct example USHORT usA; ULONG ulA; USHORT

10、 usB; UCHAR ucA; USHORT usC; EXAMPLE_SVStypedef struct example ULONG ulA; USHORT usA; USHORT usB; USHORT usC; UCHAR ucA; UCHAR ucReserved; EXAMPLE_S,基础篇之字节对齐,案例点评在定义数据结构时(尤其是涉及协议和IPC通讯的时候),没有特殊理由的话,都定义成四字节对齐;这样做可能浪费几个字节,但是不会出问题;除了数据结构总长度是四字节对齐外,每一个部分也要保证它是四字节对齐的(可以按照四字节、两字节、一字节的顺序排放数据结构中的各个域);对于无法定义

11、成四字节对齐的数据结构,如以太网II、HDLC等,则将它们强行定义成一字节对齐,以规避这个问题;对于MIPS CPU,在必须面对非四字节对齐情况时,采用编译选项方式加以解决;,目录,前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美,基础篇之字节序,X86系统:VOID QosConfigPolicy() ulDestIP = 从命令行读取用户配置的参数; pQosPolicy-ulDestIP = ulDestIP; return;主机处理:VOID QosClassify() pIp = (IP_S *)pData

12、; if (pIp-ulDestIp = pQosPolicy-ulDestIP) DoSomething(); return ;,基础篇之字节序,X86系统:VOID QosConfigPolicy() ulDestIP = 从命令行读取用户配置的参数; pQosPolicy-ulDestIP = ulDestIP; return;主机处理:VOID QosClassify() pIp = (IP_S *)pData; if (VOS_HTONL(pQosPolicy-ulDestIP) = pIp-ulDestIp ) DoSomething(); return ;,基础篇之字节序,由于历

13、史的原因,业界存在两种字节序标准:BigEndian和LittleEndian,Power PC是大头,X86是小头,有些CPU可以通过寄存器设置支持不同的字节序,例如MIPS;所谓大头就是高位在低字节,低位在高字节;小头则与此相反,以0 x345678为例,大头内存从低到高的存放次序为00,34,56,78,小头内存从低到高的存放次序为78,56,34,00;(上面的数值统一为16进制表示形式)字节序问题广泛存在于设备与设备之间、单板与单板之间、单板与底层芯片之间,只要两个处理单元的字节序不同,这个问题就存在,为了解决不同字节序的处理单元之间的通信问题,业界定义了主机序和网络序的概念,网络序

14、主要用于信息传递,一般不用于计算,其字节顺序与大头一致;除了在编码时绷紧这根弦以外,我们在器件选择时尽量选择主机序与网络序一致的芯片,同一设备的不同单板使用相同的字节序,并优先选择支持大头的芯片,这样,即使不能彻底解决问题,也可以彻底规避问题。,目录,前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美,基础篇之函数参数,在C语言中,函数通过返回值和参数与调用者交换信息,对参数理解和使用的正确与否,直接影响到函数功能能否正确实现;函数参数自身占用的存储单元在堆栈中分配,入口参数指向的数值或者地址在函数入口处拷贝到堆栈区中

15、,因此对函数参数所在存储单元的直接修改不会作用到函数之外,而对参数存储单元中存放的地址指向的存储空间的修改,则会在函数之外其作用;调用者在进行函数调用之前,必须事先申明被调用函数的原型,包括返回值类型和参数类型;,基础篇之函数参数,BOOL GetMemory(CHAR *p) /* 申请内存 */ p = (CHAR *)malloc(100); if (NULL = p) return FALSE; else return TRUE; VOID Test(void) CHAR *str = NULL; If (GetMemory(str) strcpy(str, hello world);

16、 printf(str); return;,基础篇之函数参数,CHAR* GetMemory(CHAR *p) /* 申请内存 */ *p = (CHAR *)malloc(100); return *p;VOID Test(void) CHAR *str = NULL; If (NULL != GetMemory(,目录,前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美,基础篇之返回值,在C语言中,函数的调用者通过返回值了解函数的执行情况;函数缺省的返回值类型为int,编程规范要求必须显示定义函数的返回类型;对于反

17、映了函数执行状态的返回值,调用者必须依据返回值进行相应的处理,尤其是对于函数执行异常的情形;函数的出口参数能够起到与返回值类似的作用,上面一条规则对出口参数同样适用;对于函数返回值为恒值的函数,建议使用VOID类型的返回值;,基础篇之返回值,有什么问题?#includestdlib.h“VOID main() CHAR *p; p=(CHAR *)malloc(100); VOS_Strcpy(p, “Hello World!n”); printf(p); free(p); return;,基础篇之返回值,#includestdlib.h“VOID main() CHAR *p; p=(CHA

18、R *)malloc(100); if (NULL != p) strcpy(p, “Hello World!n”); printf(p); free(p); return;,基础篇之返回值,LONG A() if (条件1) return; return VOS_OK;VOID B() if (A() DoSomeThing1(); else DoSomeThing2(); return;,基础篇之返回值,LONG A() if (条件1) return VOS_ERROR; return VOS_OK;VOID B() if (A() DoSomeThing1(); else DoSome

19、Thing2(); return;,目录,前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美,基础篇之强制类型转换,强制类型转换给C语言编程带来了极大的灵活性,也正是这种灵活性,也埋下了无数的隐患;当目的结构的空间大于源结构的空间时,要重点关注内存访问超过源结构范围的情形,可能越界;当目的结构的空间小于源结构的空间时,要重点关注对目的结构赋值不能完全覆盖源结构范围的情形,可能遗漏;与结构体之间的强制类型转换相比,基本数据结构的强制类型转换更容易出现上面描述的情况,使用的时候,一定要慎之又慎;,基础篇之类型转换目的结构小

20、于源结构,VOID B(CHAR *p) *p =1; return;VOID A() ULONG a; B(CHAR *)(a = ? ,是1吗?,基础篇之类型转换目的结构小于源结构,VOID B(CHAR *p) *p =1; return;VOID A() ULONG a; B(CHAR *)(a = ? ,是1吗?不可预知。,基础篇之类型转换目的结构大于源结构,VOID B(ULONG *p) *p =1000; return;VOID A() UCHAR a 10; B(ULONG *)(在函数B给*p赋值之前,*p的值是多少?*p赋值之后,会出现什么样的情形?,基础篇之类型转换目的

21、结构大于源结构,VOID B(ULONG *p) *p =1000; return;VOID A() UCHAR a 10; B(ULONG *)(在函数B给*p赋值之前,*p的值是多少?不可预知*p赋值之后,会出现什么样的情形?越界,目录,前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美,基础篇之switchcase,C语言使用switchcase处理一个条件的多个取值有不同的处理分支的情形;当所有的case都匹配不成功时,进入default分支,编程规范要求switchcase必须显示设置default分支,如果

22、程序从逻辑上不可能走到这个分支,可以在该分支中使用断言;结束case分支的执行最常用的办法是使用break/return,否则程序将自动进入下一个case分支继续执行;编译器对switchcase可以做优化,用空间换取时间;default分支按照编程规范,要求放在switch case的末尾,C语言本身不做强制要求;,基础篇之switchcase,VOID main( ) LONG ulCnt1=0,ulCnt2=0; CHAR* ch = “aha!” ; while (*ch) switch (*ch ) case a: case h: ulCnt2+; default: ulCnt1+;

23、 ch+; printf(%u,%un,ulCnt1,ulCnt2); return; ulCnt1和ulCnt2分别是多少?,基础篇之switchcase,VOID main( ) LONG ulCnt1=0,ulCnt2=0; CHAR* ch = “aha!” ; while (*ch) switch (*ch ) case a: case h: ulCnt2+; default: ulCnt1+; ch+; printf(%u,%un,ulCnt1,ulCnt2); return; ulCnt14 ulCnt2=3,目录,前言sizeof字节对齐字节序函数参数返回值强制类型转换Swit

24、ch case字符串溢出资源释放If规范临界资源保护简单既是美,基础篇之字符串,ULONG BuildRun(CHAR* ppBuildrun) ULONG ulLen; CHAR* pBuf; ulLen = CalculateBuildRunLen(); if (0 = ulLen) *ppBuildrun = NULL; return B_ZERO_LENGTH; pBuf = VOS_malloc(0, ulLen); if (NULL = pBuf) *ppBuildrun = NULL; return B_MALLOC_FAILED; VOS_StrCpy(pBuf, BuildR

25、unInfo); *ppBuildrun = pBuf; return VOS_OK;,基础篇之字符串,ULONG BuildRun(CHAR* ppBuildrun) ULONG ulLen; CHAR* pBuf; ulLen = CalculateBuildRunLen(); if (0 = ulLen) *ppBuildrun = NULL; return B_ZERO_LENGTH; pBuf = VOS_malloc(0, ulLen + 1); if (NULL = pBuf) *ppBuildrun = NULL; return B_MALLOC_FAILED; VOS_Str

26、Cpy(pBuf, BuildRunInfo); *ppBuildrun = pBuf; return VOS_OK;,基础篇之字符串,案例点评:作为信息输出,字符串必不可少;字符串在动态申请时少分配一个字符是非常普遍的一个错误;strlen等计算字符串长度的函数都是不考虑字符串的0结束符的;代码Review时,字符串越界问题是一个大客户,要盯紧看严;,基础篇之字符串(续),再看一个例子:LONG GetXYZHead(CHAR* pData, CHAR* pBuf) ULONG ulLen; CHAR* pTmpData = *pData, *pTmpBuf = *pBuf; ulLen =

27、 AnalysisHead(pTmpBuf); /* strcpy(pTmpData, pTmpBuf); */ /* sprintf(pTmpData, “%s”, pTmpBuf); */ /* memcpy(pTmpData,pTmpBuf, ulLen); */ return ulLen;*pBuf中存放是是XYZ协议的Peer发送过来的一段报文,这个函数负责将协议头拷贝到pData指向的空间中;假设空间是足够的,打算选择哪条语句;,基础篇之字符串(续),LONG GetXYZHead(CHAR* pData, CHAR* pBuf) ULONG ulLen; CHAR* pTmpDa

28、ta = *pData, *pTmpBuf = *pBuf; ulLen = AnalysisHead(pTmpBuf); /* strcpy(pTmpData, pTmpBuf); */ /* sprintf(pTmpData, “%s”, pTmpBuf); */ memcpy(pTmpData,pTmpBuf, ulLen); return ulLen;使用memcpy,因为没有人保证协议头中不出现0,而且协议头非常容易出现这个值,这个时候它就不再是字符串,字符串工具函数必须是专款专用,而memcpy则要宽泛得多;,基础篇之字符串(再续),VOID GetDigitString(CHAR

29、* pData, CHAR* pBuf) CHAR *pTmpData = pData, *pTmpBuf = pBuf; while (0 != (*pTmpBuf) if (0 = *pTmpBuf) *pTmpData = *pTmpBuf; pTmpData+; else break; pTmpBuf+; return;该函数的功能是将pBuf中的连续数字拷贝到pData中生成一个新的字符串,基础篇之字符串(再续),VOID GetDigitString(CHAR* pData, CHAR* pBuf) CHAR *pTmpData = pData, *pTmpBuf = pBuf;

30、while (0 != (*pTmpBuf) if (0 = *pTmpBuf) *pTmpData = *pTmpBuf; pTmpData+; else break; pTmpBuf+; *pTmpData = 0; /* 没有尾字符,就不是字符串 */ return;,目录,前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美,基础篇之溢出,#define DEFAULT_EXPIRE_TIME 300000 /* 5分钟 */VOID ARPRecordExpireTime(ARP_Entry_S *pArpEn

31、try) /* 计算表项预计老化时的时间,以系统启动以来的毫秒数表示 */ pARPEntry-ulExpireTime = GetBootTime()+DEFAULT_EXPIRE_TIME; return;VOID* ARPExpire( ARP_Entry_S *pArpEntry) ARP_Entry_s* pArpNext; while(pArpEntry) if (GetBootTime() ulExpireTime) break; pArpNext = pArpEntry-pNext; Free(pArpEntry); pArpEntry = pArpNext; return (

32、VOID *)pArpEntry;,基础篇之溢出,#define DEFAULT_EXPIRE_TIME 300000 /* 5分钟 */VOID ARPRecordExpireTime(ARP_Entry_S *pArpEntry) /* 计算表项预计老化时的时间,以系统启动以来的毫秒数表示 */ pARPEntry-ulExpireTime = GetBootTime()+ DEFAULT_EXPIRE_TIME; return;VOID* ARPExpire( ARP_Entry_S *pArpEntry) ARP_Entry_s* pArpNext; while(pArpEntry)

33、if (GetBootTime() ulExpireTime) /* ULONG溢出如何处理?包括ExpireTime溢出、GetBootTime溢出*/ /* 解决方案作为思考题 */ break; pArpNext = pArpEntry-pNext; Free(pArpEntry); pArpEntry = pArpNext; return (VOID *)pArpEntry;,基础篇之溢出,案例点评:在我们的系统中,溢出通常出现在时间处理上;系统时钟一般使用两个ULONG表示时间,精确到毫秒;上层软件使用时间时一般忽略掉高位,只保留低32位。对于LONG的情况,25天后翻转;对于ULO

34、NG的情况,49天后翻转;如果没有特殊的需要,建议使用系统提供的精确到秒的32位时钟,在LONG情况下60年翻转,基本可以不考虑这件事情;如果一定要使用毫秒钟,就需要考虑时钟翻转的情况;,基础篇之溢出(续),ULONG SequenceAdd(ULONG ulCount) ULONG ulSum = 0; while (0 = ulCount ) ulSum += ulCount; ulCount-; return ulSum;,基础篇之溢出(续),ULONG SequenceAdd(ULONG ulCount) ULONG ulSum = 0; while (0 = ulCount ) /*

35、 条件永远为真,死循环 */ ulSum += ulCount; ulCount-; return ulSum;,基础篇之溢出(续二),VOID ShowLong (ULONG ulCount) CHAR stInfo16; VOS_Sprintf(stInfo, “%ldnr”, ulCount); Printf(stInfo); return;,基础篇之溢出(续二),VOID ShowLong (ULONG ulCount) CHAR stInfo16; VOS_Sprintf(stInfo, “%lunr”, ulCount); Printf(stInfo); return;在显示无符号

36、整数时,使用正确的%描述符,基础篇之溢出(续),案例点评:要解决溢出问题,首先要明确数据结构的取值范围;无符号数和有符号数在取值范围上的差异,也容易引起溢出;若非特殊需要,不要进行有符号数和无符号数的强制类型转换,以免产生不必要的麻烦;若非特殊需要,不要进行从(U)LONG到(U)SHORT到(U)char的转换,以免产生不必要的麻烦;,目录,前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美,基础篇之资源释放,VOID PrintDigit(ULONG ulData) CHAR *pBuf; pBuf = (CHAR

37、 *)malloc(16); if (NULL = pBuf) return NULL; VOS_Sprintf(pBuf,”%lunr”, ulData); printf(pBuf); return;,基础篇之资源释放,VOID PrintDigit(ULONG ulData) CHAR *pBuf; pBuf = (CHAR *)malloc(16); if (NULL = pBuf) return NULL; VOS_Sprintf(pBuf,”%lunr”, ulData); printf(pBuf); Free(pBuf); /* Review九句箴言:看见Malloc找Free!

38、*/ return;,基础篇之资源释放(续),Node_Head_S* CreateNode(ULONG ulNType) Node_Head_S *pNode; Node_Body_S *pBody; pNode = (Node_Head_S *)malloc(sizeof(Node_Head_S); if (NULL = pNode) return NULL; pBody = (Node_Body_S *)malloc(sizeof(Node_Body_S); if (NULL = pBody) return NULL; pNode-pBody = pBody; pNode-ulNType

39、 = ulNType; return pNode;,基础篇之资源释放(续),Node_Head_S* CreateNode(ULONG ulNType) Node_Head_S *pNode; Node_Body_S *pBody; pNode = (Node_Head_S *)malloc(sizeof(Node_Head_S); if (NULL = pNode) return NULL; pBody = (Node_Body_S *)malloc(sizeof(Node_Body_S); if (NULL = pBody) Free(pNode); /* 异常分支最容易忘记打扫战场,顾头

40、也要顾尾 */ return NULL; pNode-pBody = pBody; pNode-ulNType = ulNType; return pNode;,基础篇之资源释放,案例点评资源泄漏是代码Review中最常见的错误之一申请的每个资源必须明确由谁负责释放,何时释放,在何处释放;在异常分支中,保持清醒的头脑,清理战场;在特定功能去使能时,需要完成的主要工作就是资源清退;,目录,前言sizeof字节对齐字节序函数参数返回值强制类型转换Switch case字符串溢出资源释放If规范临界资源保护简单既是美,基础篇之if规范,LONG IsZero(ULONG ulCnt) if (ulC

41、nt = 0) return W_ZERO; else return W_NONZERO; 函数的功能为:参数为0时返回W_ZERO;否则返回W_NOZERO;,基础篇之if规范,LONG IsZero(ULONG ulCnt) if (0 = ulCnt) return W_ZERO; else return W_NONZERO; 编程规范反复强调变量放在双等号的右边,常量放在左边,就是为了规避出现If (ulCnt = 0)这种语法正确,但是极有可能是笔误的情况。为了杜绝这种不必要的逻辑问题,要求必须严格遵守编程规范。,基础篇之if规范(续),If (ulCnt = ulData)Vsul

42、Cnt = ulData;If (ulCnt)VsIf (ulCnt = ulData)上面的语句语法上都是正确的,但写法哪个好?,基础篇之if规范(续),If (ulCnt = ulData)VsulCnt = ulData;If (ulCnt)VsIf (ulCnt = ulData)第一种和第三种非常容易出现笔误,为了杜绝不必要的问题,不要使用第一种方式编写程序,而用方式二替代;,基础篇之if规范(再续),VOID Test() if (Func_A() 在任何情况下是否语义都是正确的?,基础篇之if规范(再续),VOID Test() VOID Test() ULONG ulRet1,

43、 ulRet2; if (Func_A() ulRet1 = Func_A(); ulRet2 = Func_B(); if (Func_B() if (ulRet1 如果程序逻辑为Func_A的返回值为假的情况下,不执行Func_B,则上一页的程序是正确的,但是要求采用本页右侧的程序模式实现;如果Func_A和Func_B都无条件执行,再根据综合结果,决定走哪个分支,则使用本页左侧的程序;为了明确程序逻辑,同时要求使用注释加以说明,以方便后期的维护,基础篇之if规范(续三),VOS_Assert(Func_A()vsVOS_DBGASSERT(Func_A()这两个用法有什么区别?VOS_A

44、seert()用法保证在任何情况下Func_A都得到执行;VOS_DBGASSERT则与系统是打开release宏还是debug宏相关:当系统打开了debug宏时,起语义与方式1完全相同;当系统打开的是release宏,则VOS_DBGASSERT在编译时将被忽略,Func_A自然页得不到运行;使用VOS_DBGASSERT的时候要谨慎,要清楚了解不同系统宏下的不同语义,要保证两种场景下,程序逻辑都是正确的;为了避免不必要的麻烦,要求不允许在VOS_DBGASSERT中使用函数!,基础篇之if规范(续四),LONG IsA (CHAR ch) if ( a != ch) | ( A != ch

45、) return VOS_ERROR; else return VOS_OK; 函数功能为判断输入的字符是否是a或者A,如果是,则返回VOS_OK,否则返回VOS_ERROR,基础篇之if规范(续四),LONG IsA (CHAR ch) if ( a != ch) | ( A != ch) /* 逻辑恒为真,逻辑错误,笔误? */ return VOS_ERROR; else return VOS_OK; PC-LINT可以检查出逻辑恒为真或者假的逻辑表达式,基本都是我们预期之外的逻辑,PC-LINT确实是一个好东西。,目录,前言sizeof字节对齐字节序函数参数返回值强制类型转换Switc

46、h case字符串溢出资源释放If规范临界资源保护简单既是美,基础篇之临界资源保护,VOID SendMBuf(MBUF_S *pMBuf) 空闲BD数 = DRV_GetFreeBD(); 报文片数 = MBUF_GetFrag(pMBuf); if (报文片数 空闲BD数) return; /* 发送拥塞,暂时缓存 */ intr_lock(); CopyMBufIntoBD(); 空闲BD数 -= 报文片数; intr_unlock();Task SOCK: Intr:SendMBuf(pMBuf);SendMBuf(pMBuf);,基础篇之临界资源保护,VOID SendMBuf(MB

47、UF_S *pMBuf) intr_lock(); /* 彻底保护 */ 空闲BD数 = DRV_GetFreeBD(); 报文片数 = MBUF_GetFrag(pMBuf); if (报文片数 空闲BD数) intr_unlock(); /* 打扫战场 */ return (QOS_CONGEST); /* 发送拥塞,暂时缓存 */ CopyMBufIntoBD(); 空闲BD数 -= 报文片数; intr_unlock();Task SOCK: Intr:SendMBuf(pMBuf);SendMBuf(pMBuf);,基础篇之临界资源保护,案例点评这是一个经典的中断与任务之间临界资源缺

48、乏保护的案例;中断与任务之间的临界资源保护通常采用在任务中关闭中断的方式进行;关闭中断之后,对临界数据进行操作,操作完成之后再开放中断;这个案例说明对临界资源的读操作也是需要进行保护,如果读的结果是一个判断的输入条件的话;,基础篇之临界资源保护(续),VOID Show(SLIST_S *pCfgSectionList) SLIST_S *pSectionList = pCfgSectionList, *pNext; while (pSectionList) pNext = pSectionList-pNext; EXEC_Outstring(0,pSectionList-pListName)

49、; /* 有任务切换 */ pSectionList = pNext; return ;VOID FreeSection(SLIST_S *pCfgSectionList) SLIST_S *pSectionList = pCfgSectionList, *pNext; while (pSectionList) pNext = pSectionList-pNext; Free(pSectionList); pSectionList = pNext; return ;,基础篇之临界资源保护(续),VOID Show(SLIST_S *pCfgSectionList) SLIST_S *pSect

50、ionList = pCfgSectionList, *pNext; LONG lHandle; while (pSectionList) pNext = pSectionList-pNext; lHandle = SetWaitlist(pNext); EXEC_Outstring(0,pSectionList-pListName); /* 有任务切换 */ pSectionList = GetWaitlist(lHandle); return ;VOID FreeSection(SLIST_S *pCfgSectionList) SLIST_S *pSectionList = pCfgSe

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

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号