版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
2023/2/1C語言軟件編程規(guī)范工作組公司常見軟件編程低級錯誤:表達式前言這套材料作為編程規(guī)范的輔助材料,幫助大家理解編程規(guī)范背后的原理。C和C++語言是我司的主流編程語言,然而C/C++具有很多強大的語言特性,從而導致C/C++非常復雜,使得代碼更容易出現(xiàn)BUG、難以閱讀和維護。業(yè)界知名的編程規(guī)范都對C/C++容易出現(xiàn)問題的語言特性進行管理。例如MISRA(汽車工業(yè)軟件可靠性聯(lián)合會)制定的1998版的MISRAC規(guī)范指出,一些在C看來可以接受,卻存在隱患的地方有127處之多。2004版的MISRAC規(guī)范將針對C語言的規(guī)則增加到了141條。對于程序員來說,能工作的代碼并不等于“好”代碼?!昂谩贝a的指標很多,包括可讀性、可維護性、可移植性和可靠性等。出現(xiàn)網(wǎng)上問題的代碼,大多數(shù)是不良編程習慣引起的。不遵守編程規(guī)范的代碼,往往也是最不可靠的代碼。本膠片收集了常見的表達式案例,給出了相應的糾正措施。對應的編程規(guī)范:表達式的值在標準所允許的任何運算次序下都應該是相同的;用括號明確表達式的操作順序,避免過分依賴默認優(yōu)先級表達式使用默認優(yōu)先級:規(guī)則【規(guī)則】ISO9899:1990的6.5.4節(jié)對使用括號的建議:1.一元運算符,不需要使用括號
x=~a; /*一元運算符,不需要括號*/x=-a; /*一元運算符,不需要括號*/2.二元以上運算符,如果涉及多種運算符,則應該使用括號x=a+b+c; /*運算符相同,不需要括號*/x=f(a+b,c) /*運算符相同,不需要括號*/if(a&&b&&c) /*運算符相同,不需要括號*/x=(a*3)+c+d;/*運算符不同,需要括號*/x=(a==b)?a:(a–b);/*運算符不同,需要括號*/3.即使所有運算符都是相同的,如果涉及類型轉(zhuǎn)換或者量級提升,也應該使用括號控制計算的次序以下代碼將3個浮點數(shù)相加:f4=f1+f2+f3;/*除了逗號(,),邏輯與(&&),邏輯或(||)之外,C標準沒有規(guī)定同級運算符是從左還是從右開始計算,以上表達式存在2種計算次序:f4=(f1+f2)+f3或f4=f1+(f2+f3),浮點數(shù)計算過程中可能四舍五入,量級提升,計算次序的不同會導致f4的結果不同,以上表達式在不同編譯器上的計算結果可能不一樣,建議增加括號明確計算順序*/表達式使用默認優(yōu)先級(1)【問題描述】同一個目錄下發(fā)布多個頻道到一定值后,雖然是計費頻道,但實際訪問時并沒有付費定購提示,好像變成了免費模式【問題定位】問題代碼如下:StringcurDirPosition=(longCurDirPosition%100>9)?"":"0"+longCurDirPosition%100;程序的本意是根據(jù)longCurDirPosition%100>9的值,輸出”longCurDirPosition%100”或者””0”+longCurDirPosition%100”。在換行符的作用下很容易讓人以為程序是沒有問題的,但實際上程序執(zhí)行的優(yōu)先級與作者的期望不符,以上語句等價與:StringcurDirPosition=(longCurDirPosition%100>9)?"":("0"+longCurDirPosition%100);結果將輸出””或者”’0’+longCurDirPosition%100”【糾正措施】補充一對括號,修改代碼為:StringcurDirPosition=((longCurDirPosition%100>9)?"":"0“)+longCurDirPosition%100;表達式使用默認優(yōu)先級(2)【問題描述】對密碼進行MD5加密的時候,得出來的結果每次都是空?!締栴}定位】如下代碼:ucPwdLen=ucPwdLen&0xf0+0x10;程序執(zhí)行的實際優(yōu)先級為:ucPwdLen=ucPwdLen&(0xf0+0x10);【糾正措施】補充一對括號,修改代碼為:
ucPwdLen=(ucPwdLen&0xf0)
+0x10;表達式使用默認優(yōu)先級(3)【問題描述】香港鑒權二次重同步出現(xiàn)SQN混亂?!締栴}定位】如下代碼:if((sqn.seq2+1)&0x01000000>0){……….}由于>運算符優(yōu)先級大于&,
程序執(zhí)行的實際優(yōu)先級為:if((sqn.seq2+1)&(0x01000000>0))
上述if語句恒成立,導致SQN混亂?!炯m正措施】補充一對括號,修改代碼為:
if(((sqn.seq2+1)&0x01000000)>0)
表達式副作用:移植后出錯【問題描述】產(chǎn)品移植到新平臺后,下發(fā)某命令,配置不成功?!締栴}定位】問題代碼如下:Set_Config_Table(DB_Query(),Get_Next_WD());原來的平臺編譯器先執(zhí)行Get_Next_WFD(),后執(zhí)行DB_Query(),結果正確;新的平臺編譯器先執(zhí)行DB_Query(),后執(zhí)行Get_Next_WD()。在這兩個函數(shù)中,都讀寫了全局變量g_MuxData,所以兩種計算次序的執(zhí)行結果不一樣?!炯m正措施】明確語句執(zhí)行次序,函數(shù)參數(shù)不再使用表達式:intnWDID=Get_Next_WD();intnDBID=
DB_Query();Set_Config_Table(nDBID,nWDID);表達式副作用:定義【定義】副作用(side-effect)指執(zhí)行后對程序運行環(huán)境造成影響,除了無效代碼外,C/C++的每條語句要么使程序流程改變,要么產(chǎn)生副作用。每個表達式都產(chǎn)生一個值,同時可能包含副作用(例如將產(chǎn)生的值賦給一個變量)。在C/C++語言中,表達式副作用是必須而且有意為之的,但C/C++要求表達式副作用必須在sequencepoint之前結束;在兩個連續(xù)sequencepoint之間,一個對象所保存值最多只能被修改一次;如果對象的值被修改了一次,那么表達式中出現(xiàn)此對象的唯一目的只能是為了求出這個被修改的新值。否則可能產(chǎn)生非預期結果。sequencepoint是一個結算點,編譯器在此點完成所有計算。C/C++語言定義的sequencepoint如下:函數(shù)參數(shù)計算完成后,調(diào)用之前有一個sequencepoint&&||和?,這三個運算符的左側有一個sequencepoint逗號運算符左側有一個sequencepoint(注意逗號作為分隔符使用時沒有sequencepoint)分號左側有一個sequencepoint完整表達式(ifswitchwhilereturn等里面的表達式)【注意】運算符優(yōu)先級只在一個表達式中有效,兩個表達式之間如果沒有一個sequencepoint,那么先計算A表達式,還是先計算B表達式,次序不定。有時,2個sequencepoint也不保證順序執(zhí)行。表達式的非預期副作用一般不能通過增加括號消除。不確定計算次序是有意保留給編譯器進行優(yōu)化的?!疽蟆勘磉_式非預期副作用主要表現(xiàn)在使用復合表達式上,如果將復合表達式分開寫成若干個簡單表達式,就可以有效消除非預期副作用。++/--等操作符本身包含副作用(賦值功能),所以最好單獨一行。表達式副作用:規(guī)則(1)【規(guī)則】ISO9899:1990的5.1.2.3節(jié),6.2節(jié),6.3節(jié)和6.5節(jié)描述了可能產(chǎn)生非預期副作用的計算:1。自增或自減運算符:a[i]=i++;上面的表達式當中沒有sequencepoint,i的值只被修改了一次,表達式i++的目的是求出i的新值,但a[i]卻與求i值無關。所以計算結果不確定。這樣的代碼本質(zhì)上是非法的,但不產(chǎn)生編譯告警,大多數(shù)情況下也沒有PCLint告警。類似的代碼還有:i=0;i=i++;/*i與求i值無關,結果是0,1,或其它任意值,與編譯器相關*/i=0;printf(“%d%d“,i,i++)/*i與求i值無關,結果是0,1,或其它任意值,與編譯器相關*/2。函數(shù)指針函數(shù)參數(shù)和函數(shù)自身地址的計算次序未定義。p->task_start_fn(p++);求函數(shù)地址p與計算p++無關,結果是任意值。必須單獨計算p++:p->task_start_fn(p);p++;表達式副作用:規(guī)則(2)3。函數(shù)調(diào)用x=f(a)+g(b);編譯器可能先計算f(a),也可能先計算g(b),如果x的結果依賴于函數(shù)f/g的計算次序(例如,f/g被調(diào)用時修改或使用了同一個全局變量),則上面的代碼存在問題。應該修改代碼明確f/g的計算次序:x=f(a);x=x+g(b);4。函數(shù)參數(shù)函數(shù)參數(shù)通常從右到左壓棧,但函數(shù)參數(shù)的計算次序不一定與壓棧次序相同。x=func(i++,i);應該修改代碼明確先計算第一個參數(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());表達式副作用:規(guī)則(3)5。嵌套賦值語句表達式中嵌套賦值語句可能導致某些對象被賦值多次,導致結果不確定。例如,如下代碼中x被賦值了2次(編譯器:VC6.0):(x=y)=z;6。volatile訪問限定符
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 小學數(shù)學新人教版一年級下冊20以內(nèi)口算練習題大全
- 遼寧工程技術大學《建筑工程概預算課程設計A》2023-2024學年第一學期期末試卷
- 四川省瀘州市納溪區(qū)2024年中考數(shù)學適應性考試試題含答案
- 九州職業(yè)技術學院《數(shù)字化運營管理》2023-2024學年第一學期期末試卷
- 江蘇經(jīng)貿(mào)職業(yè)技術學院《兒童文學與兒童劇創(chuàng)編》2023-2024學年第一學期期末試卷
- 吉安幼兒師范高等??茖W?!缎竽廖⑸飳W實驗》2023-2024學年第一學期期末試卷
- 湖南理工學院《導游實務》2023-2024學年第一學期期末試卷
- 湖北生物科技職業(yè)學院《歷史學綜合素質(zhì)指導》2023-2024學年第一學期期末試卷
- 【物理】《彈力》(教學設計)-2024-2025學年人教版(2024)初中物理八年級下冊
- 高考物理模擬測試題(含答案)
- 《陸上風電場工程概算定額》NBT 31010-2019
- 原油脫硫技術
- 部編版初中語文七至九年級語文教材各冊人文主題與語文要素匯總一覽表合集單元目標能力點
- 工程項目收入情況統(tǒng)計表
- GB/T 29490-2013企業(yè)知識產(chǎn)權管理規(guī)范
- GB/T 14436-1993工業(yè)產(chǎn)品保證文件總則
- 湖南省鄉(xiāng)鎮(zhèn)衛(wèi)生院街道社區(qū)衛(wèi)生服務中心地址醫(yī)療機構名單目錄
- 《中外資產(chǎn)評估準則》課件第6章 英國評估準則
- FZ∕T 63006-2019 松緊帶
- 罐區(qū)自動化系統(tǒng)總體方案(31頁)ppt課件
- 工程建設項目內(nèi)外關系協(xié)調(diào)措施
評論
0/150
提交評論