目录
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
的符号是未指定的。