|
|||||||||||
| 技術(shù)交流 | 電路欣賞 | 工控天地 | 數(shù)字廣電 | 通信技術(shù) | 電源技術(shù) | 測(cè)控之家 | EMC技術(shù) | ARM技術(shù) | EDA技術(shù) | PCB技術(shù) | 嵌入式系統(tǒng) 驅(qū)動(dòng)編程 | 集成電路 | 器件替換 | 模擬技術(shù) | 新手園地 | 單 片 機(jī) | DSP技術(shù) | MCU技術(shù) | IC 設(shè)計(jì) | IC 產(chǎn)業(yè) | CAN-bus/DeviceNe |
MISRA--作為工業(yè)標(biāo)準(zhǔn)的C編程規(guī)范----摘自?? |
| 作者:gbchang 欄目:單片機(jī) |
;實(shí)在對(duì)不起原作者,我看到這篇時(shí)就沒有作者:( ;也希望大家看后不要寫上自己的名字,我們要尊重原創(chuàng)者. MISRA--作為工業(yè)標(biāo)準(zhǔn)的C編程規(guī)范 MISRA (The Motor Industry SOFTWARE Reliability Association 汽車工業(yè)軟件可靠性聯(lián) 會(huì)) 是位于英國的一個(gè)跨國汽車工業(yè)協(xié)會(huì),其成員包括了大部分歐美汽車生產(chǎn)商。其核心使 命是為汽車工業(yè)提供服務(wù)和協(xié)助,幫助廠方開發(fā)安全的、高可靠性的嵌入式軟件。這個(gè)組織 最出名的成果是所謂的MISRA C Coding STANDARD,這一標(biāo)準(zhǔn)中包括了127條C語言編碼標(biāo) 準(zhǔn),通常認(rèn)為,如果能夠完全遵守這些標(biāo)準(zhǔn),則你的C代碼是易讀、可靠、可移植和易于維 護(hù)的。最近很多嵌入式開發(fā)者都以MISRA C來衡量自己的編碼風(fēng)格,比如著名的uC/OS-II就 得意地宣稱自己99%遵守MISRA標(biāo)準(zhǔn)。而《嵌入式開發(fā)雜志》也專門載文號(hào)召大家學(xué)習(xí)。編 碼規(guī)范通常是一個(gè)公司自定的“土政策”,居然有人去做標(biāo)準(zhǔn),而且還得到廣泛的認(rèn)可,這 不禁引起我強(qiáng)烈的興趣?上н@份標(biāo)準(zhǔn)的文本需要花錢去買,而且短短幾十頁,要價(jià)非常昂 貴。MISRA在網(wǎng)上公布了一些文檔,其中有關(guān)于MISRA C Coding STANDARD的Clarification 報(bào)告,從中間你可以大致猜到MISRA標(biāo)準(zhǔn)本身是什么。我仔細(xì)閱讀了這些文檔,并且通過閱 讀其他一些介紹性文檔,大致了解了MISRA標(biāo)準(zhǔn)的主要內(nèi)容。這些條款確有過人之處,對(duì)于 C/C++語言工程項(xiàng)目的代碼質(zhì)量管理能夠起到良好的指導(dǎo)性作用,對(duì)于大部分軟件開發(fā)企業(yè) 來說,在MISRA的基礎(chǔ)上適當(dāng)修改就可以形成自己的規(guī)范。當(dāng)然其中也有一些過于嚴(yán)苛的東 西,這就需要各個(gè)開發(fā)部門靈活處理了。我個(gè)人的體會(huì),編碼規(guī)范雖然很簡(jiǎn)單,但是要完全 執(zhí)行,不折不扣,需要開發(fā)部門有很高的組織性和紀(jì)律性,并且有很好的代碼評(píng)審機(jī)制。因 此,如果能夠嚴(yán)格地遵守編碼規(guī)范,本身就是一個(gè)開發(fā)部門實(shí)力的證明。 這里不可能將所有規(guī)則一一列出(事實(shí)上正式文本我一條也沒看到),只列出一些比較有意 思的條款,讓大家有機(jī)會(huì)了解MISRA的風(fēng)格。具體的內(nèi)容,感興趣的朋友可以自己到 www.misra.org.uk去了解。 Rule 1. 嚴(yán)格遵循ANSI C89標(biāo)準(zhǔn),不允許任何擴(kuò)展。 Rule 3. 如果要嵌入?yún)R編語言,則必須將所有匯編語句包裝在C函數(shù)里,而且這些函數(shù)中只 有匯編語句,沒有常規(guī)C語句。 Rule 7. 不得使用三元操作符(? : ) Rule 10. 不得殘留被注釋掉的廢代碼。 Rule 11. 所有標(biāo)識(shí)符不超過31字符。 Rule 12. 不同名空間中的變量名不得相同。 例如: typedef struct MyStruct {... } MyStruct; (違規(guī)) struct Person { CHAR* NAME; ... }; CHAR NAME[32]; (違規(guī)) Rule 13. 不得使用CHAR, int, float, double, LONG等基本類型,應(yīng)該用自己定義的類型 顯示表示類型的大小,如CHAR8, UCHAR8, INT16, INT32, FLOAT32, LONG64, ULONG64等。 Rule 14. 不得使用類型CHAR,必須顯示聲明為unsigned CHAR或者signed CHAR。 Rule 18. 所有數(shù)字常數(shù)應(yīng)當(dāng)加上合適的后綴表示類型,例如51L, 42U, 34.12F等。 Rule 19. 禁止使用八進(jìn)制數(shù)。(因?yàn)?86U這樣的常數(shù)很容易引起誤解)。 Rule 21. 不得定義與外部作用域中某個(gè)標(biāo)識(shí)符同名的對(duì)象,以避免遮蓋外部作用域中的標(biāo) 識(shí)符。 Rule 23. 具有文件作用域的對(duì)象盡量聲名為static的。 Rule 24. 在同一個(gè)編譯單元中,同一個(gè)標(biāo)識(shí)符不應(yīng)該同事具有內(nèi)部鏈接和外部鏈接的聲 名。 這里我略作說明: 我們通常將一些放在頭文件里的變量聲名為“外部鏈接”的,如: extern UINT32 g_count; // 俗話叫變量聲明(對(duì)應(yīng)于變量定義,不分配實(shí)際空 間) 對(duì)于“使用”這個(gè)變量的.c文件來說,這很好,因?yàn)間_count始終保持外部鏈接性 質(zhì)。可是對(duì)于定義g_count(實(shí)際分配空間)的.c文件來說,如果包含了上述的頭文件,則 在這個(gè)編譯單元里就發(fā)生了內(nèi)部鏈接和外部鏈接的沖突。解決辦法是,定義g_count的文件 盡量不要包含聲名g_count的頭文件。個(gè)人感覺這不是任何時(shí)候都做得到的,尤其是在對(duì)付 遺留代碼的時(shí)候。 Rule 25. 具有外部鏈接性質(zhì)的標(biāo)識(shí)符應(yīng)該只聲明一次。 Rule 27. 外部對(duì)象不得在多個(gè)文件中聲名。 Rule 28. 禁止使用register關(guān)鍵字。 Rule 29. 自動(dòng)對(duì)象(棧對(duì)象)使用前必須賦初值。 Rule 33. 操作符&&和||的右側(cè)表達(dá)式不得具有副作用(side-effect)。 也就是說,象 if (x == 20 && ++y == 19)這樣的表達(dá)式被禁止。 Rule 35. 在返回布爾值的表達(dá)式中不得出現(xiàn)賦值操作。 也就是說,我們常用的 if (!(fp = fopen("fNAME", "r"))) { /* error */ } 被禁止。 Rule 37. 不得對(duì)有符號(hào)數(shù)施加位操作,例如 1 << 4 將被禁止,必須寫 1UL << 4; Rule 39. 不得對(duì)有符號(hào)表達(dá)式施加一元 "-" 操作符。 Rule 40. 不得對(duì)有副作用的表達(dá)式施加sizeof操作符。 Rule 42. 除了循環(huán)控制語句,不得使用逗號(hào)表達(dá)式。 Rule 44. 禁止冗余的顯式轉(zhuǎn)型。比如: double pi = (double) 3.1416F; Rule 45. 禁止從任意類型到指針的強(qiáng)制轉(zhuǎn)型,禁止從指針到任意類型的強(qiáng)制轉(zhuǎn)型。 例如:void* p = (void*)0xFEDCBA98UL; Rule 49. 顯示測(cè)試值是否為零。 Rule 50. 不得顯式判斷浮點(diǎn)數(shù)的相等性和不等性。 Rule 52. 不得遺留“永遠(yuǎn)不會(huì)用到”的代碼。 Rule 53. 所有非空語句必須具有副作用。 Rule 55. 除了SWITCH語句,不得使用標(biāo)號(hào)(label)。 Rule 56. 不得使用goto. Rule 57. 不得使用continue。 Rule 58. 除了SWITCH語句,不得使用break. Rule 59. if, else if, else, while, do..while, for語句塊必須使用{}括起。 Rule 60. 任何if..else if 語句,最后必須有一個(gè)收尾的else。例如: if (ans == 'Y') { ... } else if (ans == 'N') { ... } else if (ans == 'C') { ... } else { ; } Rule 67. 循環(huán)計(jì)數(shù)器的值不得在循環(huán)體內(nèi)修改。 Rule 70. 禁止任何直接和間接的遞歸函數(shù)調(diào)用。 Rule 82. 每個(gè)函數(shù)只能有一個(gè)推出點(diǎn)。 Rule 86. 如果一個(gè)函數(shù)可能返回錯(cuò)誤信息,則調(diào)用后必須加以測(cè)試。 Rule 92. 不應(yīng)該使用#undef Rule 95. 不得將宏作為參數(shù)傳給宏函數(shù) Rule 98. 在一個(gè)宏定義中,#或##符號(hào)只能出現(xiàn)一次。 Rule 101. 禁止指針運(yùn)算(代之以數(shù)組下標(biāo)運(yùn)算)。 Rule 102. 禁止超過兩級(jí)的指針。 Rule 104. 禁止使用指向函數(shù)的非常量指針。 Rule 106. 不得將棧對(duì)象的地址傳給外部作用域的對(duì)象。 ******************************************************************** 后面的規(guī)則針對(duì)實(shí)時(shí)嵌入式系統(tǒng),對(duì)其他類型的開發(fā)未必適用,如: Rule 118. 禁止使用動(dòng)態(tài)堆分配(也就是不得使用malloc, calloc和realloc)。 Rule 119. 禁止使用errno。 Rule 120. 禁止使用offsetof. Rule 121. 禁止使用<locale.h> Rule 122. 禁止使用setjmp, LONGjmp. Rule 123. 禁止使用<signal.h> Rule 124. 禁止使用<stdio.h>(不能用printf, scanf了。 Rule 125. 禁止使用atoi, atof, atol。(這個(gè)我很贊成,建議使用strtol, strtod等函 數(shù)) Rule 126. 禁止使用abort, exit, getenv。 Rule 1 |
| 2樓: | >>參與討論 |
| 作者: hiberhe 于 2005/3/22 22:45:00 發(fā)布:
其實(shí)有時(shí)為了特殊需要,是不可能嚴(yán)格按這樣的 |
|
| 3樓: | >>參與討論 |
| 作者: 后學(xué) 于 2005/3/23 8:17:00 發(fā)布:
著名的uC/OS-II就得意地宣稱自己99%遵守MISRA標(biāo)準(zhǔn) 這個(gè)規(guī)范要拿錢買的 Comments on the MISRA coding guidelines for C Introduction Many organisation create coding STANDARDs for SOFTWARE development. The document produced by MISRA 'Guidelines for the use of the C Language in vehicle based SOFTWARE' dated April 1998, is a GOOD base from which more sophisticated and detailed coding STANDARDs can be developed. The MISRA guidelines are of a high enough quality (regretfully many coding STANDARDs are poorly thought out) to warrant a detailed analysis. The problems with the current version of the MISRA document can be divided into several broad categories: Technical inaccuracies involving the C language as defined by WG14 Problems with the C STANDARD clause (Annex G) used as the source of coding guidelines. This annex unintentionally missed out some of the cases given in the normative portion of the document. It also contains cases that should have been removed to reflect changes (that occurred during drafts, prior to publication) in the normative portion The wording of some rules could be improved The rules in practice Looking at concrete examples can sometime be more helpful than reading a specification. A set of TEST cases would also help check adherence to the MISRA guidelines. Download MISRA C TEST cases. Those companies interested in a more substantial compiler TEST suite should look at the Perennial compiler validation suites. Comments on the Rules General points The guidelines specify that all of the rules apply equally to human and machine generated code. Some rules have their basis in psychological findings, i.e. how developers read the source. Such issues are not important in machine generated code (because such code is never read by humans). Those rules that are motivated by how humans PROCESS source code should be flagged as such, so that they may be allowed in machine generated code. Most of the rules have been taken from Annex G of the C STANDARD. This lists the unspecified, undefined and implementation defined behaviours. A program that does not use any of these constructs is much more likely to give the same results, after being PROCESSed by different implementations, than a program that does use one or more of them. In the terminology of the STANDARD such a program is strictly conforming (also, to achieve this status a program "... shall not exceed any MINIMUM implementation limit."). C9X When the MISRA document was being written the C STANDARD was ISO/IEC 9899:1990. In September 1999 voting closed on the final draft of a revision of this document. The result of the vote was YES. It is expected that by the end of the year ISO will have updated the C STANDARD to ISO/IEC 9899:1999. The commentary here refers to the 1990 STANDARD. Text within double quotation marks is quoting from this document. Any mention of 'the STANDARD' also refers to this document. C++, ISO/IEC 14882:1998 Why mention C++ in a coding STANDARD guideline? Because many people think that C is a subset of C. To make matters even worse some compiler vendors offer a SWITCH on their C++ compiler to cause it to behave like a C compiler, so they claim. The two languages have a different view of the world. Many of the language constructs that they share do behave the same way. But not all of them do. Developers who know C++ need to have some constructs brought to their attention as behaving differently in C. Specific points Rule 5: This is a broadly written rule that limits the use of characters that appear anywhere to be those that are required to be in the source character set. This excludes the characters $ and @, among others. The undefined behavior applies "... except in a character constant, a string literal, a HEADER NAME, a comment, or a prePROCESSing token that is never converted to a token ...". The implementation defined behavior kicks in when the characters are converted to an internal representation. This will occur if the characters appear in a character constant, or a string literal. The rule should be written to exclude the use of these characters within character constants and string literals. Rule 6: This rule excludes the use of an EBCDIC character set. No use of IBM 370's in embedded systems. Given that Rule 5 precludes the use of characters outside of the 91 defined by the STANDARD. It seems pointless to specify that a restricted subset of a STANDARD defining nearly 64000 characters should be used. The rule should be rewritten to specify the ASCII character set (which is already states in a round about way). Or ISO 8859-1 (Latin 1). Rule 7: Trigraphs have a well defined definition. The example given in the commentary refers to an unintentional usage which could result, if the third character were a defined trigraph, unexpected behaviour. MISRA cannot rule against unintentional usage. SOFTWARE developers working in countries whose keyboards do not offer all of the characters required to write C programs will require special EQUIPMENT, or to break this rule. Recommending that a compiler operate in a non-STANDARD mode is very bad practice. Rule 9: This precludes the use of a construct that is not supported by the C STANDARD. As such it is a pointless rule. Rule 13: C permits the basic type to be omitted, i.e., unsigned is equivalent to unsigned int. This rule needs to state that all object and function declarations shall include a basic type, via a typedefed identifier. Rule 15: This is not an enforcable coding STANDARDs rule. What is a 'defined STANDARD'? Defined by whom? Better wording, should this rule be kept, would be to require a fully documented, publically available, floating point specification. Rule 18: The commentary on this rule fails to capture the true advantage of using suffixes. The type of an integer literal depends on its VALUE and the range of VALUEs supported by a given type on a particular implementation. So, for instance, the literal 33000 has type unsigned int on a platform where int is 16 bits, but type int, if int is 32 bits. Thus it is possible for the same expression, containing integer literals, to have a different type on different compilers. Rule 22: Incorrect use of terminology here (the wording could also be read to imply that no identifiers should be declared within nested blocks). ONLY LABELS have function scope. Identifiers denoting objects have file, block or function prototype scope. This rule could state: 'Declarations of identifiers denoting objects should have block scope unless a wider scope is necessary', or 'Declarations of identifiers denoting objects should have the narrowest block scope unless a wider scope is necessary'. Rule 23: This is ONLY half the story. File scope identifiers should be explicitly declared static, or extern. Without an explicit storage class an object is a tentative definition and could be given an implicit initializer at the end of the translation unit. It is tentative in the sense that another, later, file scope, declaration of the same NAME can result in the storage class being external or static. Also the file scope declaration: const int ci; implicitly has the extern storage class in C and implicitly the static storage class in C++. Rule 24: The example is incorrect. As written the second declaration of x has static storage duration because "... contains the storage-class specifier extern, the identifier has the same linkage as any visible declaration of the identifier with file scope." The following example exhibits the intended behavior: static |
|
| 4樓: | >>參與討論 |
| 作者: and 于 2005/3/23 10:18:00 發(fā)布:
這些規(guī)則的大部分可以用工具檢查 應(yīng)該有這樣的工具吧? |
|
| 5樓: | >>參與討論 |
| 作者: 12864 于 2005/3/23 12:57:00 發(fā)布:
這么死板,循環(huán)中連break和continue都不能用 那還不是逼著我們想跳出或者重新循環(huán)的時(shí)候用goto? |
|
| 免費(fèi)注冊(cè)為維庫電子開發(fā)網(wǎng)會(huì)員,參與電子工程師社區(qū)討論,點(diǎn)此進(jìn)入 |
Copyright © 1998-2006 m.58mhw.cn 浙ICP證030469號(hào) |