1. 程式人生 > 實用技巧 >MISRA C——The Motor Industry Software Reliability Association

MISRA C——The Motor Industry Software Reliability Association

內容

修改歷史

內容

1資源

2MISRA C 2004

2.1MISRAC introduction

2.2Rule 8.1 functions shall haveprototype declaration and the prototype shall be visible at both the functiondefinition and call.

2.3Rule 8.12: When an array is declared with externallinkage, its size shall bestated explicitly or defined implicitly by initialisation.

2.4Rule10.1 The value of an expression of integer type shall not be implicitlyconverted to a different underlying type if: a) it is not a conversion to awider integer type of the same signedness, or b) the expression is complex, orc) the expression is not constant and is a function argument, or d) theexpression is not constant and is a return expression.

2.4.1例子

2.5rule 12.7Bitwise operators shall not be applied to operands whose underlying typeis signed.

2.5.1例子

2.6Rule13.6: Numeric variables being used within a for loop for iteration countingshall not be modified in the body of the loop.

2.6.1例子

2.7Rule14.2 All non-null statements shall either have at least one side effect howeverexecuted, or cause control flow to change.

2.8Rule 14.10: All if … else constructsshall be terminated with an else clause.

2.8.1例子

2.9Rule 19.4: C macros shall only expandto a braced initialiser, a constant, a string literal, aparenthesisedexpression, a strorage class specifier, or a do-while-zero construct.

2.9.1例子

2.10Rule 19.7A function should be used in preference to a function-like macro.

2.10.1例子

2.11Rule 19.10: in the definition of a function-like macro each instance of aparameter shall be enclosed in parentheses unless it is used as the operand of# or ##.

2.11.1例子

2.12Rule20.2 The names of standard librarymacros, objects and functions shall not be reused. & Rule 1.2:No reliance shall be placed on undefined or unspecified behaviour.

3MISAR C 2012

1資源

關注啟用未來公眾號,後臺回覆“MISAR C 2012”即可免費獲取“MISRA C_2012 Guidelines for the useof the C language in critical systems.pdf”文件下載連結,回覆“QAC”即可免費獲取“QAC-8.1-Win-UsersGuide.pdf”使用手冊下載連結。

MISRA官網:https://www.misra.org.uk/

MISRA C_2012 Guidelines for the use of the C language in critical systems.pdf的CSDN下載地址:

https://download.csdn.net/download/Sure_gengjia/12987445

QAC-8.1-Win-UsersGuide.pdf的CSDN下載地址:

https://download.csdn.net/download/Sure_gengjia/12987496

可結合本公眾號上一篇文章——MC9S12G128模組化分層化軟體架構之八_QAC靜態程式碼分析,在例項中體會MISRA C的規則。

2MISRA C 2004

2.1MISRA C introduction

MISRA Mission Statement: To provide assistance to the automotiveindustry in the application and creation within vehicle systems of safe andreliable software.

MISRA, The Motor Industry Software Reliability Association, is acollaboration between vehicle manufacturers, component suppliers andengineering consultancies which seeks to promote best practice in developingsafety-related electronic systems in road vehicles and other embedded systems. Tothis end MISRA publishes documents that provide accessible information forengineers and management, and holds events to permit the exchage of experiencesbetween practitioners.

MISRA使命宣言:為汽車行業中的應用和在車輛系統內建立安全可靠的軟體提供幫助。

汽車工業軟體可靠性協會(MISRA)是汽車製造商、部件供應商和工程諮詢公司之間的合作組織,旨在促進在道路車輛和其他嵌入式系統中開發安全相關電子系統的最佳實現方式。為此,MISRA出版了一些檔案,為工程師和管理層提供了可訪問的資訊,並舉辦活動以允許從業人員之間交流經驗。

2.2Rule 8.1functions shall have prototype declaration and the prototype shall be visibleat both the function definition and call.

使用原型可以使編譯器檢查函式定義和呼叫的一致性和完整性。如果沒有原型,編譯器就沒有義務承擔函式呼叫中的某些錯誤(例如,函式主體中的引數數量不同,呼叫和定義之間的引數型別不匹配)。函式介面是造成大量問題的原因,因此該規則非常重要。

給全域性函式實現函式原型的推薦方法是在標頭檔案中宣告函式(即給出函式原型),然後將標頭檔案包含在所有需要原型的程式碼檔案中。

2.3Rule8.12: When an array is declaredwith external linkage, itssize shall be stated explicitly or defined implicitly by initialisation.

當用外部連線宣告陣列時,其大小應明確宣告或通過初始化隱式定義。

int array1[ 10 ]; /*符合*/

extern intarray2[]; /*不符合*/

int array2[ ] = {0, 10, 20}; /*符合*/

儘管可以宣告不完整型別的陣列並訪問其元素,但是顯示地確定陣列大小,這樣做更安全。

2.4Rule 10.1 The value of an expression of integer type shall not beimplicitly converted to a different underlying type if: a) it is not aconversion to a wider integer type of the same signedness, or b) the expressionis complex, or c) the expression is not constant and is a function argument, ord) the expression is not constant and is a return expression.

規則10.1整型表示式的值不能隱式地轉化為以下型別:a)不是轉化為具有相同符號的更寬泛的整數型別,或者b)表示式很複雜,或者c)表示式不是常數並且是函式引數,或者d)表示式是函式返回表示式,不是常數;

規則10.1大致包括以下原則(principle):

·有符號和無符號型別之間沒有隱式轉化;

·整型和浮點型之間沒有隱式轉化;

·寬型別(widertypes)和窄型別(narrower type)之間沒有隱式轉化;

·函式引數沒有隱式轉化;

·函式返回值沒有隱式轉化;

·複雜表示式沒有隱式轉化;

2.4.1例子

extern void fool(uint8 x);

int16 func1(void)

{

fool( u8a ); /*符合*/

fool( u8a + u8b ); /*符合*/

fool( su8a ); /*不符合*/

fool( u16a ); /*不符合*/

fool( 2 ); /*不符合*/

fool( 2U ); /*符合*/

fool( (uint8)2 ) /*符合*/

… s8a + u8a… /*不符合*/

s8b = u8a; /*不符合*/

… u8a + 5… /*不符合*/

… u8a + 5U … /*符合*/

… u8a + (uint8) 5 … /*符合*/

u8a = u16a; /*不符合*/

u8a = (uint8) u16a; /*符合*/

u8a = 5UL; /*不符合*/

… u8a + 10UL; /*符合*/

u8a = 5U; /*符合*/

… u8a >> 3 /*符合*/

… u8a >> 3U /*符合*/

… s32a + 80000 /*符合*/

… s32a + 80000L /*符合*/

u8a = u8b + u8c; /*符合*/

s16a = u8a + u8n; /*不符合*/

s32a = u8b + u8c; /*不符合*/

u8a = f32a; /*不符合*/

s32a = 1.0; /*不符合*/

return s32a; /*不符合*/

return 20000; /*符合*/

return 20000L; /*不符合*/

return s16a; /*符合*/

return s8a; /*不符合*/

return u16a; /*不符合*/

}

2.5rule 12.7Bitwise operators shall not be applied to operandswhose underlying type is signed.

按位運算子不得應用於其基礎型別為帶符號的運算元。

按位運算(〜,>,>> =,&,&=,^,^ =,|和| =)通常對有符號整數沒有意義。例如,如果右移將符號位移到數字中,或者左移將數字位移到符號位,則會出現問題。

2.5.1例子

extern S16 test(void)

{

s16a = (S16)(s16a << 2); /*不符合*/

s16a = s16a >> 1; /*不符合*/

s16a = s16a & 3; /*不符合*/

s16a = s16a | 5; /*不符合*/

s16a = (S16)~s16a; /*不符合*/

u8a = (U8)(u8a << 2);

u8a = u8a >> 1;

u8a = u8a & 0x3U;

u8a = u8a | 0x5U;

u8a = (U8)~u8a;

return 1;

}

2.6Rule 13.6: Numeric variables being used within a for loop foriteration counting shall not be modified in the body of the loop.

在for迴圈中用於迭代計數的數字變數不得在迴圈主體中修改。

迴圈計數器不得在迴圈主體中修改。但是,可以在迴圈中修改表示邏輯值的其他迴圈控制變數,例如,指示已完成某些操作的標誌,然後在for語句中對其進行測試。

2.6.1例子

flag = 1;

for(I = 0; (i < 5) && (flag == 1); i++)

{

flag = 0; /*符合,允許提前終止迴圈*/

i = i + 3;/*不符合,改變了迴圈的計數器*/

}

2.7Rule 14.2 All non-null statements shall either have at least oneside effect however executed, or cause control flow to change.

所有非null語句無論執行如何,都應當有至少一個side effect,或者對導致控制流改變。

任何無副作用且不會導致控制流改變的語句(空語句除外)通常會指示程式設計錯誤,因此,應對此類語句執行靜態檢查。例如,以下語句在執行時不一定具有副作用:

x >= 3u; /*不符合,x和3比較,但是比較的結果被丟棄*/

2.8Rule 14.10: All if … else constructs shall be terminated with an else clause.

所有的if… else結構都應當以else子句結束。

只要if語句後接一個或多個else if語句,則適用此規則。最後的else後面應帶有else語句。對於簡單的if語句,則無需包含else語句。

最後的else語句的要求是防禦性程式設計。else語句應採取適當的措施或包含有關為何不採取任何措施的適當註釋。這與在switch語句(15.3)中具有final default子句的要求一致。

2.8.1例子

簡單的if語句:

if ( x < 0 )

{

x = 0;

} /*else not needed*/

if else if結構:

if ( x < 0 )

{

x = 0;

}

else if ( y < 0 )

{

x = 3;

}

else /*這個else子句是需要的,即使這個else永遠到不了*/

{

}

2.9Rule19.4: C macros shall only expand to a braced initialiser, a constant, a stringliteral, aparenthesised expression, a strorage class specifier, or ado-while-zero construct.

C語言中的巨集只能擴充套件為帶括號的初始化程式、常量、字串字面量、帶括號的表示式、儲存類說明符或者一個do-while-zero結構。

這些是巨集唯一允許的使用。儲存類說明符和型別限定符包括諸如extern、static和const之類的關鍵字。驚醒替換時,#define的任何其他使用都可能導致意外行為,或導致很難度的程式碼。

特別是,除非是用do-while構造,否則不得使用巨集來定義語句或語句的一部分。巨集也不應重新定義語言的語法。巨集替換列表中所有型別的方括號(){}[]均應保持平衡。

do-while-zero構造(見下面的例子)是在巨集主體中具有完整語句的唯一允許的機制。do-while-zero構造用於包裝一系列一個或多個語句並確保正確的行為。注意:必須在巨集主體的末尾省略分號。

2.9.1例子

/*以下都是符合規範的例子*/

#define PI 3.14159F /* constant */

#define XSTAL 1000000 /* constant */

#define CLOCK (XTAL/16) /* constant expression */

#define PLUS2(X) ((X) +2) /* macro expanding toexpression */

#define STOR extern /* storage classspecifier */

#define INIT(value) {(value),0, 0} /* braced initializer */

#define CAT (PI) /*parenthesized expression */

#define FILE_A “filename.h” /* string literal */

#defineREAD_TIME_32() \

do\

{\

DISABLE_INTERRUPTS(); \

time_now = ( uint32_t ) TIMER_HI <<16; \

time_now = time_now | ( uint32_t )TIMER_LO; \

ENABLE_INTERRUPTS(); \

}while(0)/*example ofdo-while-zero*/

/*下面的例子不符合規範*/

#define int32_t long /*使用typedef代替*/

#defineSTARTIF if( /*不平衡()與語言重新定義*/

#defineCAT PI /*沒有括號的表示式*/

2.10Rule 19.7 A function should be used in preference to a function-likemacro.

應優先使用函式而不是類似函式的巨集。

儘管巨集可以提供比函式更快的速度,但是函式提供了更安全,更健壯的機制。對於引數的型別檢查,以及類函式巨集可多次評估引數的問題。

2.10.1例子

#define MAX( A , B) (((A)> (B)) ? (A) : (B)) /* MISARviolation */

#define MMAX ( 14 +32 ) /*符合*/

#define10 /*符合*/

2.11Rule19.10: in the definitionof a function-like macro each instance of a parameter shall be enclosed inparentheses unless it is used as the operand of # or ##.

在類函式的巨集的定義中,引數的每個例項都應該括在括號裡,除非其用作#或##的運算元。

2.11.1例子

#define abs(x) (((x) >= 0) ?(x) : -(x)) /*符合*/

#define abs(x) ((x >= 0) ? x :-x) /*不符合*/

如果不遵循此規則,當前處理器將巨集替換為程式碼時,運算元的優先順序可能不是期望的結果。

如果第二個不正確的定義替換到表示式中:

z = abs( a – b );

替換後的結果:

z = ((a – b >= 0) ? a – b : -a – b);

-a – b表示式相當於(-a)-b,而不是期望的-(a-b)。在巨集定義中,將所有的引數都放在括號中能避免此類問題。

2.12Rule 20.2 The names ofstandard library macros, objects and functions shall not be reused. &Rule 1.2: No reliance shall be placed on undefined or unspecifiedbehaviour.

標準庫的巨集、物件和函式的名字不能被重用。

如果程式設計師使用新版本的標準庫巨集,物件或函式(例如,增強功能或輸入值的檢查),則修改後的巨集,物件或函式應具有新名稱。這是為了避免關於是否正在使用標準巨集,物件或函式或是否正在使用該函式的修改版本的混淆。因此,例如,如果編寫了新版本的sqrt函式以檢查輸入是否為負,則該新函式不應命名為“sqrt”,而應被賦予一個新名稱。

3MISARC2012

行勝於言