MISRA C规范
2.语言扩展
2.1 汇编语言应该通过a.汇编函数,b.C函数,c.宏三种方式封装并隔离汇编指令; 例如
#define NOP asm(" NOP");
2.2 源代码应该使用/*...*/类型注释,而不是使用//这样C99类型和C++类型的注释,其作为对C90的扩展;
2.3 字符/*不应该出现在注释中,因为C不支持注释的嵌套;
2.4 当源代码段不需要被编译时,应当使用条件编译完成例如#if、#elif、#else、#endif、#ifdef、#ifndef;
3 文档
3.1 所选编译器中整数除法的实现需要确定;
3.2 所有#pragma指令使用需要给出注释;
3.3 对位域的使用需要文档化,对结构体位域的使用可参考;
https://www.cnblogs.com/balingybj/p/4780358.html
4 字符集
4.1 只能使用ISO C标准中定义的转义字符串(escape sequence);
http://m.php.cn/manual/view/34273.html
https://en.wikipedia.org/wiki/Escape_sequences_in_C
4.2 标识符
1、无论是内部标识符还是外部标识符的有效字符都不能多于31;
2、具有内部作用域的标识符不应当使用具有外部作用域的标识符相同的名称,这会隐藏外部标识符,PS:作用域主
要看{};
3、typedef的名字应该是唯一标识符,不允许被重用;
4、不同tag标签必须是唯一的,不能够被重用,例如struct stag,union stag就不可以;
5、不管作用域如何,具有静态存储器的对象或者函数标识符不应被系统内所有源文件中重用;PS:这很容易理解
6、不考虑作用域,一个命名空间中不应该存在于另一个命名空间中标识符拼写相同的标识符,除了struct和union
中成员名字,PS:意思enum也不可以。
5 类型
5.1 单纯的char类型只能用于存储和使用字符值;
5.2 signed char和unsigned char类型只能用于存储和使用数字值;
5.3 应当使用指示大小和符号的typedef 替代基本数据类型;
5.4 位域只能被定义为unsigned int或者signed int类型,同时unsigned int类型位域长度至少为2bits;
6 常量
6.1 不要使用八进制常量和八进制的转义字符串;
7 声明与定义
7.1 外部对象或者函数应该声明在唯一的文件中;
7.2 在文件范围内声明和定义的所有对象和函数应该具有内部连接,除非需要外部连接。例如如果一个变量或者函数只在一
个文件中使用,就用static修饰;
8 初始化
8.1 自动变量在使用前应该被赋值;
8.2 在枚举列表中"="不能显式用于除首元素之外的元素上,除非所有元素都显式初始化;PS:很容易理解,怕出错。
9 数据类型转换
9.1 隐式和显式类型转换
1、对于数值丢失、符号丢失、精度丢失这些危险的类型换换需要强制使用显式类型转换来完成;
2、对于函数形、函数返回值、复杂表达式都必须使用显式类型转换;
9.2 整数后缀
1、所有unsigned类型的常量都必须后缀"U";
9.3 指针类型转换
1、void*指针可以被自动转化为特定指针类型;
2、函数指针不能够转换到除整型之外其他类型的指针;
3、某类型对象指针不能和其他不同类型对象指针之间进行强制转换;PS:不同结构体对象指针就不能相互转换;
4、如果指针指向的类型带有const或者voliate限定符,移除限定符的强制转换时不允许的;
10 表达式
1、不要过分依赖运算符优先级,但是也不要使用过多的括号;
2、表达式的值在标准允许的任何运算次序下都应该是相同的;
以下例子是不被允许的:
x = b[i]+i++; x = func(i++,i); p->task_start_fn(p++); x = f(a) + g(a);
3、位运算符不能用于基本类型是有符号类型的操作数上;
4、移位运算符的右手操作数应该小于左手操作数的基本类型的位宽;
5、一元减运算符不能用在无符号类型的表达式上;
其他C标准:
1. VS2010/2012不支持C99标准,支持C89标准。