软件编程低级错误:表达式ppt课件_第1页
软件编程低级错误:表达式ppt课件_第2页
软件编程低级错误:表达式ppt课件_第3页
软件编程低级错误:表达式ppt课件_第4页
软件编程低级错误:表达式ppt课件_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

2020/5/4,C语言软件编程规范工作组,公司常见软件编程低级错误:表达式,前言,这套材料作为编程规范的辅助材料,帮助大家理解编程规范背后的原理。C和C+语言是我司的主流编程语言,然而C/C+具有很多强大的语言特性,从而导致C/C+非常复杂,使得代码更容易出现BUG、难以阅读和维护。业界知名的编程规范都对C/C+容易出现问题的语言特性进行管理。例如MISRA(汽车工业软件可靠性联合会)制定的1998版的MISRAC规范指出,一些在C看来可以接受,却存在隐患的地方有127处之多。2004版的MISRAC规范将针对C语言的规则增加到了141条。对于程序员来说,能工作的代码并不等于“好”代码。“好”代码的指标很多,包括可读性、可维护性、可移植性和可靠性等。出现网上问题的代码,大多数是不良编程习惯引起的。不遵守编程规范的代码,往往也是最不可靠的代码。本胶片收集了常见的表达式案例,给出了相应的纠正措施。对应的编程规范:表达式的值在标准所允许的任何运算次序下都应该是相同的;用括号明确表达式的操作顺序,避免过分依赖默认优先级,表达式使用默认优先级:规则,【规则】ISO9899:1990的6.5.4节对使用括号的建议:1.一元运算符,不需要使用括号x=a;/*一元运算符,不需要括号*/x=-a;/*一元运算符,不需要括号*/2.二元以上运算符,如果涉及多种运算符,则应该使用括号x=a+b+c;/*运算符相同,不需要括号*/x=f(a+b,c)/*运算符相同,不需要括号*/if(a/*除了逗号(,),逻辑与(程序的本意是根据longCurDirPosition%1009的值,输出”longCurDirPosition%100”或者”0”+longCurDirPosition%100”。在换行符的作用下很容易让人以为程序是没有问题的,但实际上程序执行的优先级与作者的期望不符,以上语句等价与:StringcurDirPosition=(longCurDirPosition%1009)?:(0+longCurDirPosition%100);结果将输出”或者”0+longCurDirPosition%100”【纠正措施】补充一对括号,修改代码为:StringcurDirPosition=(longCurDirPosition%1009)?:0“)+longCurDirPosition%100;,表达式使用默认优先级(2),【问题描述】对密码进行MD5加密的时候,得出来的结果每次都是空。【问题定位】如下代码:ucPwdLen=ucPwdLen,表达式使用默认优先级(3),【问题描述】香港鉴权二次重同步出现SQN混乱。【问题定位】如下代码:if(sqn.seq2+1)原来的平台编译器先执行Get_Next_WFD(),后执行DB_Query(),结果正确;新的平台编译器先执行DB_Query(),后执行Get_Next_WD()。在这两个函数中,都读写了全局变量g_MuxData,所以两种计算次序的执行结果不一样。【纠正措施】明确语句执行次序,函数参数不再使用表达式:intnWDID=Get_Next_WD();intnDBID=DB_Query();Set_Config_Table(nDBID,nWDID);,表达式副作用:定义,【定义】副作用(side-effect)指执行后对程序运行环境造成影响,除了无效代码外,C/C+的每条语句要么使程序流程改变,要么产生副作用。每个表达式都产生一个值,同时可能包含副作用(例如将产生的值赋给一个变量)。在C/C+语言中,表达式副作用是必须而且有意为之的,但C/C+要求表达式副作用必须在sequencepoint之前结束;在两个连续sequencepoint之间,一个对象所保存值最多只能被修改一次;如果对象的值被修改了一次,那么表达式中出现此对象的唯一目的只能是为了求出这个被修改的新值。否则可能产生非预期结果。sequencepoint是一个结算点,编译器在此点完成所有计算。C/C+语言定义的sequencepoint如下:函数参数计算完成后,调用之前有一个sequencepoint上面的表达式当中没有sequencepoint,i的值只被修改了一次,表达式i+的目的是求出i的新值,但ai却与求i值无关。所以计算结果不确定。这样的代码本质上是非法的,但不产生编译告警,大多数情况下也没有PCLint告警。类似的代码还有:i=0;i=i+;/*i与求i值无关,结果是0,1,或其它任意值,与编译器相关*/i=0;printf(“%d%d“,i,i+)/*i与求i值无关,结果是0,1,或其它任意值,与编译器相关*/2。函数指针函数参数和函数自身地址的计算次序未定义。p-task_start_fn(p+);求函数地址p与计算p+无关,结果是任意值。必须单独计算p+:p-task_start_fn(p);p+;,表达式副作用:规则(2),3。函数调用x=f(a)+g(b);编译器可能先计算f(a),也可能先计算g(b),如果x的结果依赖于函数f/g的计算次序(例如,f/g被调用时修改或使用了同一个全局变量),则上面的代码存在问题。应该修改代码明确f/g的计算次序:x=f(a);x=x+g(b);4。函数参数函数参数通常从右到左压栈,但函数参数的计算次序不一定与压栈次序相同。x=func(i+,i);应该修改代码明确先计算第一个参数:i+;x=func(i,i);前面曾经举的网上问题案例也是类似的代码:Fun(shared_ptr(newWidget),shared_ptr(newWidget);Set_Config_Table(DB_Query(),Get_Next_WD();,表达式副作用:规则(3),5。嵌套赋值语句表达式中嵌套赋值语句可能导致某些对象被赋值多次,导致结果不确定。例如,如下代码中x被赋值了2次(编译器:VC6.0):(x=y)=z;6。volatile访问限定符volatile表示可能被其它途径更改的变量,例如硬件自动更新的寄存器。编译器不会优化对volatile变量的读取。例如,下面的写法可能无法实现作

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论