博客專欄

        EEPW首頁 > 博客 > 編程規范哪家強 我把Misra C講一講

        編程規范哪家強 我把Misra C講一講

        發布人:三德子 時間:2022-05-03 來源:工程師 發布文章

        俗語講,無規矩不成方圓,有敬畏才知行止。 

        煌煌人世間,這邊是周吳鄭王,那邊廂何呂施張,大家遵守同一個規矩才能你來我往。 

        國有國法,行有行規,每一行都要定出個規范和章程,才不至于天下熙熙,母鴨對公雞,天下攘攘,你推我也搡。 

        貓有貓的道,夜里不睡覺,狗有狗的道,見樹就撒尿。電子工程師寫代碼,耶耶切克鬧,編程規范就有好幾套。 

        比如被美國佬視為眼中釘、怎么打也打不死的華為,有一套自己的C語言編程規范,開篇便是大家風范:清晰第一,簡潔為美,頗有幾分道可道、非常道的玄妙。 

        再比如被美國佬看做肉中刺,嚷嚷著連著Jack Ma一塊兒起訴的阿里,也有自己的一套編碼規范,雖然不局限于C語言,也妥妥的“風清揚”氣場,起范兒。 

        這兩家都是中國IT行業的翹楚,搞一套自家的編程規范,有點振臂高呼,號召大家卷上一卷的意思。 

        不過,沒有金剛鉆,就不攬那瓷器活。小公司固然沒能力,卻也沒意愿搞一套自家的編程規范,因為Misra C自有現成,做個善假于物也的君子,不亦樂乎? 

        1Misra C是啥

        Misra C”是The Motor Industry Software Reliability Association C Coding Standard汽車工業軟件可靠性聯合會制定的C編碼標準的首字母縮寫,最早的版本問世于1998是專門針對汽車工業軟件安全性的一種C語言編碼規范。 

        想要進宮,必先自宮,馬要拉車,得先閹割。也可以認為,提高程序的可靠性健壯性,Misra C這把手術刀天馬行空的C語言特性進行了無情的閹割。 

        葵花寶典(1).jpg

        說到這里,為了避免老表們產生不必要的誤解,不得不提上兩句。

        華為和阿里編程規范的側重點實則與Misra C有所不同,它們的關注點并不在程序的健壯性這種“里子”,而在于統一代碼風格這個“面子”。為的是將程序員代碼私產轉化為公產,以代碼的可讀性提高人員更迭對應的可維護性和可重用性。 

        里子很重要,面子當然也很重要。因為,代碼是軟件的最終體現形式,將人的設計思維轉換為機器語言的橋梁它不僅要實現功能,被機器所讀懂,更重要的是依照熟悉的代碼風格和良好的可讀性,它可以清晰地向閱讀它的碼農們表達設計思想 

        就跟現在上海的同胞既要捅嗓子又要捅鼻子一樣,代碼也得兩頭通!

        核酸檢測(1).jpg 

        這些代碼風格如何,給大家幾個例子,自行體會一下吧。 

        比如說華為規定每行代碼不能超過120個字,阿里規定每行代碼不能超過80個字,再比如每個函數不能超過80行。。。 

        這些根據顯示器上能夠容納的字符數和行數而針對代碼風格進行的規范,正是Misra C所不曾涉及的。 

        Misra C不重形式,更重實質,它所關注的是代碼的安全性、穩定性、魯棒性。比如說所有switch語句里都要有break,以防止意外發生時找不到處理分支。 

        再比如說,雖然使用遞歸能夠非常‘優雅’地實現某個功能,但是Misra C規定:一個函數不能直接或者間接地調用自己! 

        Anyway,華為阿里編程規范和Misra C的終極目的都是為了讓程序員寫出一手好代碼,方向是一致的,道路是不同的。也可以說: 

        皓月當空,以手指月,華為和阿里在乎的是那只手,而Misra C在乎的是那輪月。

        以手指月(1).jpg

        2、Misra C的背景

        黑格爾說:凡是存在的,都是合理的。那么,誕生于上個世紀70年代初的C語言,怎么就在上個世紀末的時候,迎來了Misra C這么個婆婆? 

        或者說,Misra C的合理性在哪兒?這個婆婆,看不上C大姐哪一點了? 

        C語言身材苗條(結構緊湊)、能說會道(表達能力強)、溫順體貼(靈活性強),在嵌入式碼農這個圈圈里,很是招人喜歡。 

        碼農們喜歡換著花樣擺弄C語言,有時還會故意使用一些花里胡哨的特性。但是,正如張無忌他媽說過‘越是漂亮的女人越會騙人一樣,越是靈活的特性,越會導致粗心大意的編碼人員寫出危險的代碼。 

        梅西說:“我不是天生強大,我只是天生要強”。灑家說:“C語言并非天生安全,它只是天生就帶著缺陷”。 

        所以,為了對治C語言先天的固有缺陷,Misra C橫空出世,針砭C弊。 

        金庸老爺子說:萬物相生相克,凡是毒物,七步之內必有解****。C語言先天帶毒,自然有Misra C來跟它相愛相殺一番。 

        最初,Misra C只面向汽車行業,針對的是汽車行業的嵌入式開發,后來,從MISRA-C:2004開始它便擴大了覆蓋范圍,面向其它高安全性系統了。 

        Misra C(1).jpg

        畢竟,都是嵌入式,都在搞C代碼開發,大哥能比二哥好哪去?所以,Misra C的觸角迅速延伸到安全性至關重要的許多其他應用領域搞起了獨樂樂不如眾樂樂的大生態。 

        周公制禮,天下歸心。規矩,是讓人心安的,Misra C,也可以讓嵌入式行業的一眾用戶心安。

        3、Misra C規則原因解讀

        Misra C的規則干巴巴,看官看著打哈哈。 

        網上有不少對Misra C規則的解讀,無需灑家再置喙。灑家是覺得,規則解讀固然重要,但更重要的是,搞清楚Misra C制定這些規則的原因,咱不僅要知其然,更要知其所以然。

        3.1 靈活是陷阱

        C語言的靈活性是讓碼農對之愛不釋手的原因之一,但是,汝之蜜糖,彼之砒霜。對高手而言,靈活的編程方式和語法規則是他們發揮高超水平的蜜糖,對菜鳥來說,便成了處處挖坑的砒霜。 

        比如if(val++)if(++val) 這兩種寫法里,它可以同時把if語句和val的累加操作結合在一起,對高手而言,能省掉一行代碼,確實很靈活,但有時卻會違背了菜鳥碼農的本意。 

        因為這里面有兩個陷阱。 

        其一,前種寫法是先用當前val進行判斷,再讓val累加,后一種寫法則是先讓val累加,再用累加后的val判斷。 

        此外,如果val是個指針,菜鳥又可知,這些累加并非加一,而是加上指針本身的長度呢? 

        所以,靈活性是一把雙刃劍,刀刃向內還是向外全憑本事。 

        正所謂:二八佳人體似酥,你要是沒那金剛杵,她就暗里教君骨髓枯。

        3.2 C語言的運行時檢查能力較弱

        灑家曾經寫過一段時間的Java,剛開始寫時,便對它能動態檢查數組越界贊不絕口,啥時候C代碼也能這樣該有多好?就拿下面來說, 

        uint8_t Val[10];

        Val[idx] = 0; 

        若是運行時idx =10Val[idx] = 0這個操作便會直接越界到和Val相鄰的變量(假設為Ino)那里。 

        假設您在別的地方給Ino賦了值,根據其值執行不同的動作邏輯,本來一切歲月靜好,結果神不知、鬼不覺,Ino好端端地突變成了0,您還不得直呼見鬼了! 

        這種bug,來無影去無蹤,一下就挖個大深坑。你左看看,右瞧瞧,怎么也想不到是鄰居甩的刀!

        3.3 電腦的行為同程序員預期的不同

        baby甩掉的黃曉明曾經說過:“我不要你覺得,我要我覺得。。。” 

        我要我覺得(1).jpg

        C代碼里,也經常出現程序員以為這樣,而電腦卻以為那樣的情況。 

        比如說您寫了下面三行代碼:

        uint8_t  Pres;

        uint16_t Ev_pres;

        Ev_pres = (uint16_t)((uint32_t)(Pres * 350) / 255); 

        您自認并非菜鳥,自以為然地在心中嘀咕著:“菜鳥們應該想不到,這里面的奧妙之處在于Pres * 350的結果可能會超出uint16_t的上限65535,數據會發生截斷,所以,把這個結果加個(uint32_t)就萬無一失了 

        可是,你以為這樣,老板就給你加雞腿了?加個棒槌! 

        因為,如果Pres=200,你以為Ev_pres=200*350/255=274,但電腦運行后的結果卻是Ev_pres=17。 

        為什么呢?聰明的讀者可能看出來了,問題出在(uint32_t)(Pres * 350)這里,Pres * 350在數據截斷之后再(uint32_t)已經沒有意義了,應該改成下面這種寫法:

        Ev_pres = (uint16_t)((uint32_t)Pres * 350 / 255); 

        這個例子也說明,要想和電腦哥倆好,括號的位置很重要!

        總結:

        搞電子的都知道,代碼寫得好,調試的活就能省不少,代碼寫得糟,調試時踩的坑少不了。 

        所以,按捺住那顆蠢蠢欲動的心,老老實實地遵循規范標準,就能少埋坑,少踩雷,切切實實地碼出質量,碼出穩定性來。 

        筒子們,加油!


        *博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。



        關鍵詞: 編程規范 Misra C 汽車

        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 舞钢市| 余江县| 孟连| 尚志市| 鄂尔多斯市| 宜宾市| 桐庐县| 永平县| 分宜县| 中卫市| 南澳县| 景泰县| 航空| 铜鼓县| 新化县| 云南省| 泾源县| 堆龙德庆县| 朝阳市| 顺平县| 大石桥市| 牡丹江市| 安达市| 稷山县| 天津市| 新晃| 四会市| 蒙城县| 高台县| 日喀则市| 姚安县| 新巴尔虎左旗| 外汇| 神农架林区| 南丰县| 阿克陶县| 许昌县| 宽甸| 方正县| 文昌市| 沁源县|