博客專欄

        EEPW首頁 > 博客 > 編程規范哪家強 Misra C姊妹篇再上場

        編程規范哪家強 Misra C姊妹篇再上場

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

        據說,在中國的演藝界,有兩個圈最講究規矩了。 

        一個是小品圈,以東北王為代表,一個頭磕到地上,便入了趙家門,得守趙氏家法。 

        還有一個便是相聲界,長幼尊卑更是秩序森嚴,跟師父鬧掰便是叛出師門,在相聲界基本上便沒有了立足之地。 

        還有便是軍隊,更是紀律嚴明,講究個戰前且莫議論紛紛,開戰便要萬眾一心。因為,主帥有令,將士效命,才能攻無不克,戰無不勝。您不信?君不見,楊主簿啃著雞肋上斷頭臺否? 

        楊修.jpg

        編程這種“小事”,同樣也得守規矩!

        1、編程規范的重要性

        之前,灑家寫過一篇《編程規范哪家強 我把Misra C講一講》,大致講了Misra C誕生的背景及其規則背后的原因。今天,灑家不惜筆墨,苦口婆心,跟大家談一談編程規范的重要性。 

        孔老夫子總結自己一生時曾曰:吾十有五而志于學,三十而立,四十而不惑,五十而知天命,六十而耳順,七十而從心所欲,不逾矩。 

        吾十有五而志于學.jpg

        西方人秉承Follow your heart,搞得毒品泛濫,小姐滿大街。孔老夫子卻能做到“從心所欲,不逾矩”,為什么? 

        因為,當持戒成為一種習慣,不逾矩便成了從心所欲的自然。持守戒律、遵守規矩非但不會處處束縛你,反而讓你在道德準則社會秩序允許的范圍內得到最大程度的自由。那些淺薄的西方人,是把這個邏輯搞反了呀! 

        風箏是自由的,是因為有根線,讓它既能翱翔于九天,又能隨時隨刻被拉牽。火車是自由的,是因為有一雙鐵軌,讓它既能風馳電掣越千山,又能平平穩穩進車站。代碼是自由的,是因為有規范,讓它既能把您的所思所想付諸實踐,又能避免翻車,給你瞎搗亂。 

        對于寫代碼來說,編程規范不會限制自由,它只會限制滋生混亂 

        一個不遵循規范的代碼不僅僅虱子多了真犯愁,bug多了直撓頭,還會在閱讀、修改、維護上會遇到理解上的障礙 

        對于剛上手不久的菜鳥級碼農來說,遵循規范意味著嚴格的自律、小心翼翼和偏執,但這能減少bug和隱患而且,一旦養成了習慣,習慣就變成了自然,這時候,不符合規則的代碼一入你的法眼,你就不由自主地要把它改掉,讓這些不規矩的代碼快滾蛋。 

        對一個組織而言,遵守統一的編程規范意味著書同文、車同軌,就像月老的紅絲線,把大家伙的心兒緊相連,從而大幅提高協作效率,真正做到團隊作戰。

        2、面向可靠性/安全的設計規范

        這世上有一個神奇的二八定律,比方說20%的人掌握著世界上80%的財富,20%的人干著80%的活。。。 

        干過大批量量產電子產品的攻城獅們還發現,20%的時間能干成80%的活,接下來要用80%的時間,把剩下20%的細節好好打磨。 

        之所以如此,是因為這些產品在上市前需要經過研發團隊非常嚴苛的反復測試。為什么要反復測試?不要問,問就是不懂!難不成,出了問題,你能牛得像特斯拉那樣非但拒絕認錯,還要教育教育用戶? 

        那么,“嚴苛”在哪里?“反復測試”些什么呢?除了正常邏輯、常規條件,還需要反復測試Corner case(邊界條件/邊角案例)! 

        佛說,萬事萬物,因緣和合而生,因緣別離而滅。大部分條件下,因緣和合,產品穩定運行,但一旦超過了某個臨界點,滿足了邊界條件,如果處理失當,就可能因緣別離,功能失常了。 

        何謂邊界條件?其定義并不統一,從實際應用來講,一般是指很少發生的情景、參數異常、噪聲或者極端情況。開發產品需要充分考慮邊界條件,或施加約束,針對處理,或圍住撈凈,避免漏網,它會直接關乎到產品的可靠性和功能安全。 

        但是,產品的可靠性是設計出來的,而非靠測試測出來。在最初的設計階段就納入功能安全的理念,才能強本固基,扎下可靠性的底盤。 

        對于內嵌C代碼的電子產品而言,可靠性/功能安全和代碼的靈活性卻往往是一體兩面,王不見王,二龍不相見C語言的靈活性,可以助力高手鬼斧神工,天外飛仙,也能讓菜鳥處處挖坑,埋下風險。 

        凡事皆是破壞容易建設難,在靈活的語言特性下,要把程序寫糟很容易,寫好很難如果沒有一個嚴格、安全的設計規范來把關,很容易把代碼寫爛 

        Misra C,正是為了對治C語言的靈活性、提高代碼的可靠性橫空出世的尚方寶劍。 

        Misra C規則大多來自一線工程師/專家多年的編程實踐提煉于多年軟件設計的教訓經驗一時理解不了,也是正常表現,您只需多多編程實戰,切不可自以為是,兩眼朝天。 

        畢竟,法律條文都會看,但只有羅老師的粉絲過千萬!

        羅翔.jpg

        3MISRA-C 規則分類及舉例

        務虛務實,相得益彰,上點干貨,才見真章。下面跟大家分享,Misra C針對C語言的籬笆下的一些樁。

         3.1 被誤解的語言特性

        3.1.1 char只用作字符

        畢達哥拉斯學派有一句名言:萬物皆數。生于俄羅斯的我國大詩仙李白對此深有體會,因為他曾喃喃自語:白發三千丈,緣愁似個長?也曾大聲驚呼:飛流直下三千尺,疑是銀河落九天。 

        詩仙何以不識數?因為,在他的慧眼里,數不是數,是帶著詩情畫意的字符。在計算機的世界里,也有這樣一個獨特的數據類型char,你也不要把它當成數,而要當成字符。 

        首先,這意味著它的取值區間是[-128,127],其次,char型應該只用做字符”,不要當成“數字”來用。看看下面這個例子: 

        char i;

        i = 131;

        if(i > 130){

            Fun();

        }

        如你所愿地執行Fun()?當然,不會! 

        所以,Misra C規則5.1規定,“單純的char類型只能用于存儲和使用字符值  

        3.1.2自動變量不會自動初始化

        先上個例子:

        uint8_t Fun(void)

        {

            uint8_t i;

            ...

            if(0 == i){

                Fun2();

            }

        } 

        同樣,不會執行Fun2() 

        很多人會自以為是地想,科技在發展,時代在進步,現在的開發環境這么友好,它肯定會把變量i自動賦值為0的吧? 

        答案是No! C語言里,只有全局變量和靜態局部變量會默認賦值為0,非靜態的局部變量隨機賦值,所以,Misra C規則9.1規定:所有自動變量在使用前都應該被賦值! 

        3.2 增強程序的清晰

        3.2.1 定義清晰的數據類型

        應該使用指示了大小和符號的typedef 以代替基本數據類型灑家在16位單片機上定義的常用類型如下:

        typedef signed char    sint8_t;

        typedef unsigned char  uint8_t;

        typedef signed int      sint16_t;

        typedef unsigned int   uint16_t;  

        typedef float          float32_t;

        typedef unsigned long  uint32_t;  

        3.2.2 不要使用逗號運算符

        比如下面這段代碼占了5行:

        if(TRUE == Val){

            motor->pointer = 0;

            motor->pointer_old = 0;

            motor->cmd_dir = CLKWISE;

        }

        有的偏執狂為了精簡行數,改成下面這樣的兩行:

        if(TRUE == Val)

        motor->pointer = 0, motor->pointer_old = 0, motor->cmd_dir = CLKWISE;

         

        好多人get不到這種方式的缺點。想想一個場景,如果這是你從別人手中接手的代碼,看著怪不怪?是不是懷疑哪個逗號搞錯了,應該改成分號來著?

        程序員惡趣味.jpg 

        這背后,是律己從寬、料敵從嚴的人性啊! 

        3.3杜絕奇技淫巧-笨拙則魯棒

        對工程師來說,天才的設計是真正的浪漫。在自己得意的作品中留下一些小心思,是碼農們對庸常生活的一種反抗。 

        于是,各種花哨的小動作就出現在了本該嚴謹的編碼實踐中。舉個例子:

        uint8_t *** ptr;

        指向xx的指針的指針的指針多燒腦,多“美妙”。 

        可是,君子藏器于身,以鈍示人,以鋒策己。搞得這么花里胡哨,真以為過了一段時間自己能記牢?

         

        3.4 不要依賴編譯器

        不要過分依賴C表達式中的運算符優先規則

        比如下面這個程序:

        uint8_t  ial,iah;

        uint16_t ia; 

        ia = ial + iah << 8; 

        初衷很簡單,將兩個八位數據連接成一個16位數據。上面的錯誤在哪里?‘+’的優先級大于‘<<’,所以應該改成下面這種形式: 

        ia = ial + (iah << 8); 

         

        不知不覺,文章就變得又臭又長了。收工!

         

        文:三少爺

         

         


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

        超聲波液位計相關文章:超聲波液位計原理


        液位計相關文章:磁翻板液位計原理





        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 南开区| 汕尾市| 沈阳市| 威信县| 册亨县| 民权县| 巴塘县| 马边| 霍州市| 绿春县| 沁源县| 阿拉善盟| 丹寨县| 黄龙县| 师宗县| 股票| 牟定县| 贡觉县| 江门市| 崇义县| 郓城县| 龙井市| 扎兰屯市| 和田县| 石首市| 霍邱县| 工布江达县| 海原县| 蒙城县| 城固县| 沙河市| 鹤峰县| 温宿县| 阜阳市| 昆明市| 滦平县| 阿拉善盟| 珠海市| 色达县| 华亭县| 铜川市|