目錄
1.標準C環境準則
錯誤示例1:未定義行為(整數溢出)
錯誤示例2:未指定行為(函數調用順序)
錯誤示例3:語言擴展(GCC內置函數)
錯誤示例4:關鍵未指定行為(位域順序)
錯誤示例5:未定義行為(解引用空指針)
錯誤示例6:違反標準C語法(C11特性在C99編譯器中)
錯誤示例7:未定義行為(數組越界)
錯誤示例8:未指定行為(整數提升)
相關文章如下:
1、《MISRA C-2012準則之標準C環境準則》
2、《MISRA C-2012準則之未使用的代碼的處理》
3、《MISRA C-2012準則之注釋》
4、《MISRA C-2012準則之標識符》
5、《MISRA C-2012準則之常量》
6、《MISRA C-2012準則之聲明與定義》
一.MISRA C簡介
MISRA C是由汽車產業軟件可靠性協會(MISRA)提出的C語言開發標準。其目的是在增進嵌入式系統的安全性及可移植性。
MISRA C一開始主要是針對汽車產業,不過其它產業也逐漸開始使用MISRA C:包括航天、電信、 ?國防、醫療設備、鐵路等領域中都已有廠商使用MISRA C。
MISRA C的第一版是在1998年發行,一般稱為MISRA-C:1998。在2004年時發行了第二版的MISRA C,稱作MISRA-C:2004。2012年發布第三版,為當前最新有效的C語言規范版本,稱為MISRA-C:2012。 MISRA C不能100%保證程序不出問題,但是能盡可能的預防,總結一下,基本上使用MISRA C具有以下五個維度的優勢:
1、提升可靠性
2、提升可讀性
3、提升可移植性
4、提升可維護性
5、提升安全性
二.標準C環境準則
必需。程序應不包含違反標準C語法和限制的內容,也不應超出執行的轉換限制。程序只能使用C語言及其庫中所選標準版本中指定的特性,比如目前比較流行的C語言版本是C99,如果項目中使用的編譯器只支持到C99的話就不可使用C11的特性。
建議。盡量不使用語言擴展。即不要用編程語言擴展屬性,否則會降低程序的可移植性。
必需。不得出現未定義或關鍵的未指定行為。
錯誤示例1:未定義行為(整數溢出)
#include <stdio.h>int main() {int x = 2147483647; // INT_MAXx = x + 1; // 整數溢出(未定義行為)printf("%d\n", x);return 0;
}
問題:在C中,有符號整數溢出是未定義行為。
錯誤示例2:未指定行為(函數調用順序)
#include <stdio.h>int f() { printf("f\n"); return 1; }
int g() { printf("g\n"); return 0; }int main() {int result = f() + g(); // f和g的執行順序未指定return 0;
}
問題:函數調用順序是未指定的,可能導致不可預測的輸出。
錯誤示例3:語言擴展(GCC內置函數)
#include <stdio.h>int main() {int x = __builtin_expect(1, 1); // GCC擴展printf("%d\n", x);return 0;
}
問題:__builtin_expect
是GCC特有的擴展,降低可移植性。
錯誤示例4:關鍵未指定行為(位域順序)
struct S {unsigned int a : 1;unsigned int b : 2;
};int main() {struct S s = {1, 2};// 位域的存儲順序(a在前還是b在前)是未指定的return 0;
}
問題:位域的存儲順序是未指定的,可能導致不同平臺行為不一致。
錯誤示例5:未定義行為(解引用空指針)
#include <stdio.h>int main() {int *p = NULL;*p = 42; // 解引用空指針(未定義行為)return 0;
}
問題:解引用空指針是未定義行為。
錯誤示例6:違反標準C語法(C11特性在C99編譯器中)
#include <stdio.h>int main() {_Thread_local int x; // C11特性,在C99編譯器中不支持return 0;
}
問題:_Thread_local
是C11引入的,不能在僅支持C99的編譯器中使用。
錯誤示例7:未定義行為(數組越界)
#include <stdio.h>int main() {int arr[5];arr[10] = 42; // 數組越界(未定義行為)return 0;
}
問題:數組越界訪問是未定義行為。
錯誤示例8:未指定行為(整數提升)
#include <stdio.h>int main() {char c = 200;int x = c; // char提升為int的符號取決于實現printf("%d\n", x);return 0;
}
問題:char
提升為int
的符號是未指定的。