軟件編程低級(jí)錯(cuò)誤:表達(dá)式_第1頁
軟件編程低級(jí)錯(cuò)誤:表達(dá)式_第2頁
軟件編程低級(jí)錯(cuò)誤:表達(dá)式_第3頁
軟件編程低級(jí)錯(cuò)誤:表達(dá)式_第4頁
軟件編程低級(jí)錯(cuò)誤:表達(dá)式_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

2023/2/1C語言軟件編程規(guī)范工作組公司常見軟件編程低級(jí)錯(cuò)誤:表達(dá)式前言這套材料作為編程規(guī)范的輔助材料,幫助大家理解編程規(guī)范背后的原理。C和C++語言是我司的主流編程語言,然而C/C++具有很多強(qiáng)大的語言特性,從而導(dǎo)致C/C++非常復(fù)雜,使得代碼更容易出現(xiàn)BUG、難以閱讀和維護(hù)。業(yè)界知名的編程規(guī)范都對(duì)C/C++容易出現(xiàn)問題的語言特性進(jìn)行管理。例如MISRA(汽車工業(yè)軟件可靠性聯(lián)合會(huì))制定的1998版的MISRAC規(guī)范指出,一些在C看來可以接受,卻存在隱患的地方有127處之多。2004版的MISRAC規(guī)范將針對(duì)C語言的規(guī)則增加到了141條。對(duì)于程序員來說,能工作的代碼并不等于“好”代碼?!昂谩贝a的指標(biāo)很多,包括可讀性、可維護(hù)性、可移植性和可靠性等。出現(xiàn)網(wǎng)上問題的代碼,大多數(shù)是不良編程習(xí)慣引起的。不遵守編程規(guī)范的代碼,往往也是最不可靠的代碼。本膠片收集了常見的表達(dá)式案例,給出了相應(yīng)的糾正措施。對(duì)應(yīng)的編程規(guī)范:表達(dá)式的值在標(biāo)準(zhǔn)所允許的任何運(yùn)算次序下都應(yīng)該是相同的;用括號(hào)明確表達(dá)式的操作順序,避免過分依賴默認(rèn)優(yōu)先級(jí)表達(dá)式使用默認(rèn)優(yōu)先級(jí):規(guī)則【規(guī)則】ISO9899:1990的6.5.4節(jié)對(duì)使用括號(hào)的建議:1.一元運(yùn)算符,不需要使用括號(hào)

x=~a; /*一元運(yùn)算符,不需要括號(hào)*/x=-a; /*一元運(yùn)算符,不需要括號(hào)*/2.二元以上運(yùn)算符,如果涉及多種運(yùn)算符,則應(yīng)該使用括號(hào)x=a+b+c; /*運(yùn)算符相同,不需要括號(hào)*/x=f(a+b,c) /*運(yùn)算符相同,不需要括號(hào)*/if(a&&b&&c) /*運(yùn)算符相同,不需要括號(hào)*/x=(a*3)+c+d;/*運(yùn)算符不同,需要括號(hào)*/x=(a==b)?a:(a–b);/*運(yùn)算符不同,需要括號(hào)*/3.即使所有運(yùn)算符都是相同的,如果涉及類型轉(zhuǎn)換或者量級(jí)提升,也應(yīng)該使用括號(hào)控制計(jì)算的次序以下代碼將3個(gè)浮點(diǎn)數(shù)相加:f4=f1+f2+f3;/*除了逗號(hào)(,),邏輯與(&&),邏輯或(||)之外,C標(biāo)準(zhǔn)沒有規(guī)定同級(jí)運(yùn)算符是從左還是從右開始計(jì)算,以上表達(dá)式存在2種計(jì)算次序:f4=(f1+f2)+f3或f4=f1+(f2+f3),浮點(diǎn)數(shù)計(jì)算過程中可能四舍五入,量級(jí)提升,計(jì)算次序的不同會(huì)導(dǎo)致f4的結(jié)果不同,以上表達(dá)式在不同編譯器上的計(jì)算結(jié)果可能不一樣,建議增加括號(hào)明確計(jì)算順序*/表達(dá)式使用默認(rèn)優(yōu)先級(jí)(1)【問題描述】同一個(gè)目錄下發(fā)布多個(gè)頻道到一定值后,雖然是計(jì)費(fèi)頻道,但實(shí)際訪問時(shí)并沒有付費(fèi)定購提示,好像變成了免費(fèi)模式【問題定位】問題代碼如下:StringcurDirPosition=(longCurDirPosition%100>9)?"":"0"+longCurDirPosition%100;程序的本意是根據(jù)longCurDirPosition%100>9的值,輸出”longCurDirPosition%100”或者””0”+longCurDirPosition%100”。在換行符的作用下很容易讓人以為程序是沒有問題的,但實(shí)際上程序執(zhí)行的優(yōu)先級(jí)與作者的期望不符,以上語句等價(jià)與:StringcurDirPosition=(longCurDirPosition%100>9)?"":("0"+longCurDirPosition%100);結(jié)果將輸出””或者”’0’+longCurDirPosition%100”【糾正措施】補(bǔ)充一對(duì)括號(hào),修改代碼為:StringcurDirPosition=((longCurDirPosition%100>9)?"":"0“)+longCurDirPosition%100;表達(dá)式使用默認(rèn)優(yōu)先級(jí)(2)【問題描述】對(duì)密碼進(jìn)行MD5加密的時(shí)候,得出來的結(jié)果每次都是空?!締栴}定位】如下代碼:ucPwdLen=ucPwdLen&0xf0+0x10;程序執(zhí)行的實(shí)際優(yōu)先級(jí)為:ucPwdLen=ucPwdLen&(0xf0+0x10);【糾正措施】補(bǔ)充一對(duì)括號(hào),修改代碼為:

ucPwdLen=(ucPwdLen&0xf0)

+0x10;表達(dá)式使用默認(rèn)優(yōu)先級(jí)(3)【問題描述】香港鑒權(quán)二次重同步出現(xiàn)SQN混亂。【問題定位】如下代碼:if((sqn.seq2+1)&0x01000000>0){……….}由于>運(yùn)算符優(yōu)先級(jí)大于&,

程序執(zhí)行的實(shí)際優(yōu)先級(jí)為:if((sqn.seq2+1)&(0x01000000>0))

上述if語句恒成立,導(dǎo)致SQN混亂?!炯m正措施】補(bǔ)充一對(duì)括號(hào),修改代碼為:

if(((sqn.seq2+1)&0x01000000)>0)

表達(dá)式副作用:移植后出錯(cuò)【問題描述】產(chǎn)品移植到新平臺(tái)后,下發(fā)某命令,配置不成功?!締栴}定位】問題代碼如下:Set_Config_Table(DB_Query(),Get_Next_WD());原來的平臺(tái)編譯器先執(zhí)行Get_Next_WFD(),后執(zhí)行DB_Query(),結(jié)果正確;新的平臺(tái)編譯器先執(zhí)行DB_Query(),后執(zhí)行Get_Next_WD()。在這兩個(gè)函數(shù)中,都讀寫了全局變量g_MuxData,所以兩種計(jì)算次序的執(zhí)行結(jié)果不一樣。【糾正措施】明確語句執(zhí)行次序,函數(shù)參數(shù)不再使用表達(dá)式:intnWDID=Get_Next_WD();intnDBID=

DB_Query();Set_Config_Table(nDBID,nWDID);表達(dá)式副作用:定義【定義】副作用(side-effect)指執(zhí)行后對(duì)程序運(yùn)行環(huán)境造成影響,除了無效代碼外,C/C++的每條語句要么使程序流程改變,要么產(chǎn)生副作用。每個(gè)表達(dá)式都產(chǎn)生一個(gè)值,同時(shí)可能包含副作用(例如將產(chǎn)生的值賦給一個(gè)變量)。在C/C++語言中,表達(dá)式副作用是必須而且有意為之的,但C/C++要求表達(dá)式副作用必須在sequencepoint之前結(jié)束;在兩個(gè)連續(xù)sequencepoint之間,一個(gè)對(duì)象所保存值最多只能被修改一次;如果對(duì)象的值被修改了一次,那么表達(dá)式中出現(xiàn)此對(duì)象的唯一目的只能是為了求出這個(gè)被修改的新值。否則可能產(chǎn)生非預(yù)期結(jié)果。sequencepoint是一個(gè)結(jié)算點(diǎn),編譯器在此點(diǎn)完成所有計(jì)算。C/C++語言定義的sequencepoint如下:函數(shù)參數(shù)計(jì)算完成后,調(diào)用之前有一個(gè)sequencepoint&&||和?,這三個(gè)運(yùn)算符的左側(cè)有一個(gè)sequencepoint逗號(hào)運(yùn)算符左側(cè)有一個(gè)sequencepoint(注意逗號(hào)作為分隔符使用時(shí)沒有sequencepoint)分號(hào)左側(cè)有一個(gè)sequencepoint完整表達(dá)式(ifswitchwhilereturn等里面的表達(dá)式)【注意】運(yùn)算符優(yōu)先級(jí)只在一個(gè)表達(dá)式中有效,兩個(gè)表達(dá)式之間如果沒有一個(gè)sequencepoint,那么先計(jì)算A表達(dá)式,還是先計(jì)算B表達(dá)式,次序不定。有時(shí),2個(gè)sequencepoint也不保證順序執(zhí)行。表達(dá)式的非預(yù)期副作用一般不能通過增加括號(hào)消除。不確定計(jì)算次序是有意保留給編譯器進(jìn)行優(yōu)化的?!疽蟆勘磉_(dá)式非預(yù)期副作用主要表現(xiàn)在使用復(fù)合表達(dá)式上,如果將復(fù)合表達(dá)式分開寫成若干個(gè)簡單表達(dá)式,就可以有效消除非預(yù)期副作用。++/--等操作符本身包含副作用(賦值功能),所以最好單獨(dú)一行。表達(dá)式副作用:規(guī)則(1)【規(guī)則】ISO9899:1990的5.1.2.3節(jié),6.2節(jié),6.3節(jié)和6.5節(jié)描述了可能產(chǎn)生非預(yù)期副作用的計(jì)算:1。自增或自減運(yùn)算符:a[i]=i++;上面的表達(dá)式當(dāng)中沒有sequencepoint,i的值只被修改了一次,表達(dá)式i++的目的是求出i的新值,但a[i]卻與求i值無關(guān)。所以計(jì)算結(jié)果不確定。這樣的代碼本質(zhì)上是非法的,但不產(chǎn)生編譯告警,大多數(shù)情況下也沒有PCLint告警。類似的代碼還有:i=0;i=i++;/*i與求i值無關(guān),結(jié)果是0,1,或其它任意值,與編譯器相關(guān)*/i=0;printf(“%d%d“,i,i++)/*i與求i值無關(guān),結(jié)果是0,1,或其它任意值,與編譯器相關(guān)*/2。函數(shù)指針函數(shù)參數(shù)和函數(shù)自身地址的計(jì)算次序未定義。p->task_start_fn(p++);求函數(shù)地址p與計(jì)算p++無關(guān),結(jié)果是任意值。必須單獨(dú)計(jì)算p++:p->task_start_fn(p);p++;表達(dá)式副作用:規(guī)則(2)3。函數(shù)調(diào)用x=f(a)+g(b);編譯器可能先計(jì)算f(a),也可能先計(jì)算g(b),如果x的結(jié)果依賴于函數(shù)f/g的計(jì)算次序(例如,f/g被調(diào)用時(shí)修改或使用了同一個(gè)全局變量),則上面的代碼存在問題。應(yīng)該修改代碼明確f/g的計(jì)算次序:x=f(a);x=x+g(b);4。函數(shù)參數(shù)函數(shù)參數(shù)通常從右到左壓棧,但函數(shù)參數(shù)的計(jì)算次序不一定與壓棧次序相同。x=func(i++,i);應(yīng)該修改代碼明確先計(jì)算第一個(gè)參數(shù):i++;x=func(i,i);前面曾經(jīng)舉的網(wǎng)上問題案例也是類似的代碼:Fun(shared_ptr<Widget>(newWidget),shared_ptr<Widget>(newWidget));Set_Config_Table(DB_Query(),Get_Next_WD());表達(dá)式副作用:規(guī)則(3)5。嵌套賦值語句表達(dá)式中嵌套賦值語句可能導(dǎo)致某些對(duì)象被賦值多次,導(dǎo)致結(jié)果不確定。例如,如下代碼中x被賦值了2次(編譯器:VC6.0):(x=y)=z;6。volatile訪問限定符

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論