| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1100 人关注过本帖, 1 人收藏
标题:【转贴】MISRA-C:1998(解读)
取消只看楼主 加入收藏
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
结帖率:100%
收藏(1)
 问题点数:0 回复次数:1 
【转贴】MISRA-C:1998(解读)
标题:MISRA-C:1998(解读)

2012-05-07 09:32:24



MISRA--作为工业标准的C编程规范

    MISRA (The Motor Industry Software Reliability Association 汽车工业软件可靠性联会) 是位于英国的一个跨国汽车工业协会,其成员包括了大部分欧美汽车生产商。其核心使命是为汽车工业提供服务和协助,帮助厂方开发安全的、高可靠性的嵌入式软件。这个组织最出名的成果是所谓的MISRA C Coding Standard,这一标准中包括了127条C语言编码标准,通常认为,如果能够完全遵守这些标准,则你的C代码是易读、可靠、可移植和易于维护的。最近很多嵌入式开发者都以MISRA C来衡量自己的编码风格,比如著名的uC/OS-II就得意地宣称自己99%遵守MISRA标准。而《嵌入式开发杂志》也专门载文号召大家学习。编码规范通常是一个公司自定的“土政策”,居然有人去做标准,而且还得到广泛的认可,这不禁引起我强烈的兴趣。可惜这份标准的文本需要花钱去买,而且短短几十页,要价非常昂贵。MISRA在网上公布了一些文档,其中有关于MISRA C Coding Standard的Clarification报告,从中间你可以大致猜到MISRA标准本身是什么。我仔细阅读了这些文档,并且通过阅读其他一些介绍性文档,大致了解了MISRA标准的主要内容。这些条款确有过人之处,对于C/C++语言工程项目的代码质量管理能够起到良好的指导性作用,对于大部分软件开发企业来说,在MISRA的基础上适当修改就可以形成自己的规范。当然其中也有一些过于严苛的东西,这就需要各个开发部门灵活处理了。我个人的体会,编码规范虽然很简单,但是要完全执行,不折不扣,需要开发部门有很高的组织性和纪律性,并且有很好的代码评审机制。因此,如果能够严格地遵守编码规范,本身就是一个开发部门实力的证明。

这里不可能将所有规则一一列出(事实上正式文本我一条也没看到),只列出一些比较有意思的条款,让大家有机会了解MISRA的风格。具体的内容,感兴趣的朋友可以自己到www.去了解。

Rule 1. 严格遵循ANSI C89标准,不允许任何扩展。

Rule 3. 如果要嵌入汇编语言,则必须将所有汇编语句包装在C函数里,而且这些函数中只有汇编语句,没有常规C语句。
   
Rule 7. 不得使用三元操作符(? : )

Rule 10. 不得残留被注释掉的废代码。

Rule 11. 所有标识符不超过31字符。

Rule 12. 不同名空间中的变量名不得相同。
         例如:
             typedef struct MyStruct {... } MyStruct;  (违规)

             struct Person {
                char* name;
                ...
              };

             char name[32];  (违规)

Rule 13. 不得使用char, int, float, double, long等基本类型,应该用自己定义的类型显示表示类型的大小,如CHAR8, UCHAR8, INT16, INT32, FLOAT32, LONG64, ULONG64等。

Rule 14. 不得使用类型char,必须显示声明为unsigned char或者signed char。

Rule 18. 所有数字常数应当加上合适的后缀表示类型,例如51L, 42U, 34.12F等。

Rule 19. 禁止使用八进制数。(因为086U这样的常数很容易引起误解)。

Rule 21. 不得定义与外部作用域中某个标识符同名的对象,以避免遮盖外部作用域中的标识符。

Rule 23. 具有文件作用域的对象尽量声名为static的。

Rule 24. 在同一个编译单元中,同一个标识符不应该同事具有内部链接和外部链接的声名。

         这里我略作说明:
        
          我们通常将一些放在头文件里的变量声名为“外部链接”的,如:
         extern UINT32 g_count;  // 俗话叫变量声明(对应于变量定义,不分配实际空间)

         对于“使用”这个变量的.c文件来说,这很好,因为g_count始终保持外部链接性质。可是对于定义g_count(实际分配空间)的.c文件来说,如果包含了上述的头文件,则在这个编译单元里就发生了内部链接和外部链接的冲突。解决办法是,定义g_count的文件尽量不要包含声名g_count的头文件。个人感觉这不是任何时候都做得到的,尤其是在对付遗留代码的时候。

Rule 25. 具有外部链接性质的标识符应该只声明一次。

Rule 27. 外部对象不得在多个文件中声名。

Rule 28. 禁止使用register关键字。

Rule 29. 自动对象(栈对象)使用前必须赋初值。

Rule 33. 操作符&&和||的右侧表达式不得具有副作用(side-effect)。
         也就是说,象 if (x == 20 && ++y == 19)这样的表达式被禁止。

Rule 35. 在返回布尔值的表达式中不得出现赋值操作。
         也就是说,我们常用的 if (!(fp = fopen("fname", "r"))) { /* error */ }
          被禁止。

Rule 37. 不得对有符号数施加位操作,例如 1 << 4 将被禁止,必须写 1UL << 4;

Rule 39. 不得对有符号表达式施加一元 "-" 操作符。

Rule 40. 不得对有副作用的表达式施加sizeof操作符。

Rule 42. 除了循环控制语句,不得使用逗号表达式。

Rule 44. 禁止冗余的显式转型。比如: double pi = (double) 3.1416F;

Rule 45. 禁止从任意类型到指针的强制转型,禁止从指针到任意类型的强制转型。
         例如:void* p = (void*)0xFFFF8888UL;

Rule 49. 显示测试值是否为零。

Rule 50. 不得显式判断浮点数的相等性和不等性。

Rule 52. 不得遗留“永远不会用到”的代码。

Rule 53. 所有非空语句必须具有副作用。

Rule 55. 除了switch语句,不得使用标号(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 语句,最后必须有一个收尾的else。例如:
         if (ans == 'Y') {
            ...
          }
          else if (ans == 'N') {
            ...
          }
          else if (ans == 'C') {
            ...
          }
          else {
            ;
          }

Rule 67. 循环计数器的值不得在循环体内修改。

Rule 70. 禁止任何直接和间接的递归函数调用。

Rule 82. 每个函数只能有一个推出点。

Rule 86. 如果一个函数可能返回错误信息,则调用后必须加以测试。

Rule 92. 不应该使用#undef

Rule 95. 不得将宏作为参数传给宏函数

Rule 98. 在一个宏定义中,#或##符号只能出现一次。

Rule 101. 禁止指针运算(代之以数组下标运算)。

Rule 102. 禁止超过两级的指针。

Rule 104. 禁止使用指向函数的非常量指针。

Rule 106. 不得将栈对象的地址传给外部作用域的对象。

********************************************************************
后面的规则针对实时嵌入式系统,对其他类型的开发未必适用,如:

Rule 118. 禁止使用动态堆分配(也就是不得使用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。(这个我很赞成,建议使用strtol, strtod等函数)

Rule 126. 禁止使用abort, exit, getenv。

Rule 127. 禁止使用<time.h>

                              摘自互联网资源,以备后用~!
 

本文引用通告地址:http://huxiongwei.spaces.
搜索更多相关主题的帖子: 嵌入式软件 Software 可靠性 生产商 C语言 
2013-08-10 21:41
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
MISRA C Rules
 The following is a summary of the MISRA C rules. This document is not a definitive list these rules,
 which are only and completely defined in "MISRA Guidelines for the use of the C language in
 vehicle based software".
 Environment
 1 (req): All code shall conform to ISO 9899 standard, with no extensions permitted.
 2 (adv): Code written in languages other than C should only be used if there is a defined interface
 standard for object code to which the compiler/assembler for both languages conform
 3 (adv): Assembler language functions that are called from C should be written as C functions
 containing only in-line assembly language, and in-line assembly language should not be
 embedded in normal C code
 4 (adv): Provision should be made for appropriate run-time checking
 Character Sets
 5 (req): Only those characters and escape sequences that are defined in the IOS C standard shall be
 used
 6 (req): Values of character types shall be restricted to a defined and documented subset of ISO
 10646-1
 7 (req): Tri-graphs shall not be used
 8 (req): Multibyte characters and wide string literals shall not be used
 Comments
 9 (req): Comments shall not be nested
 10 (adv): Sections of code should not be commented out
 Identifiers
 11 (req): Identifiers shall not rely on the significance of more than 31 characters.
 Compiler/linker shall check to ensure that 31 char significance and case sensitivity are
 supported for external identifiers
 12 (adv): Identifiers in different namespace shall not have the same spelling.
 Structure members are an exception
 Types
 13 (adv): The basic types char, int, short, long, double and float should not be used. Specific-length
 equivalents should be typedef’d for the specific compiler, and these names used in the code
 14 (req): The type char shall always be declared as unsigned char or signed char .
 See rule 13
 15 (adv): Floating point implementations should comply with a defined floating point standard
 16 (req): The underlying bit representation of floating point numbers shall not be used in any way
 by the programmer
 17 (req): typedef names shall not be reusedConstants
 18 (adv): Numeric constants should be suffixed to indicate type if possible
 19 (req): Octal constants shall not be used
 Zero is okay
 Declarations and Definitions
 20 (req): All object and function identifiers shall be declared before use
 21 (req): Identifiers in an inner scope shall not use the same name as an identifier in an outer scope,
 and therefore hide that identifier
 22 (adv): Declaration of object should be at function scope unless a wider scope is necessary
 23 (adv): All declarations at file scope should be static if possible
 24 (req): Identifiers shall not simultaneously have both internal and external linkage in the same
 translation unit
 25 (req): An identifier with an external linkage shall have exactly one external definition
 26 (req): If objects are declared more than once they shall have compatible declarations
 27 (adv): External objects should not be declared in more than one file
 28 (adv): The register storage class specifier should not be used
 29 (req): The use of a tag shall agree with its declaration
 Initialisation
 30 (req): All automatic variables shall have a value assigned to them before use
 31 (req): Braces shall be used to indicate and match the structure in the non-zero initialisation of
 arrays and structures
 32 (req): In an enumerator list the = construct shall not be used to explicitly initialise members other
 than the fist unless it is used to initialise all items
 Operators
 33 (req): The right hand operand of a && or || shall not contain side effects
 34 (req): The operands of a logical && or || shall be primary expressions
 A single identifier, constant or parenthesised expression
 35 (req): Assignment operators shall not be used in expressions that return Boolean values
 36 (adv): Logical operators shall not be confused with bitwise operators
 37 (req): Bitwise operations shall not be performed on signed integer types
 38 (req): The right hand operand of a shift operator shall lie between zero and one less the width in
 bits of the left hand operand
 39 (req): The unary minus operator shall not be applied to an unsigned expression
 40 (adv): The sizeof operator should not be used on expressions that contain side effects
  41 (adv): The implementation of integer division in the chosen compiler should be determined,
 documented and taken into account
 42 (req): The comma operator shall not be used, except in the control expression of a for loop
 Conversions
 43 (req): Implicit conversions that might result in a loss of information shall not be used44 (adv): Redundant explicit cast should not be used
 45 (req): Type casting from any type to or from pointers shall not be used
 Expressions
 46 (req): The value of an expression shall be the same under any order of evaluation that the
 standard permits
 47 (adv): No dependence should be placed on C’s precedence rules
 48 (adv): Mixed precision arithmetic should use explicit casting to generate the desired result
 49 (adv): Tests of a value against zero should be explicit, unless the operant is effectively Boolean
 50 (req): Floating point variables shall not be tested for exact inequality or inequality
 51 (adv): Evaluation of constant unsigned integer expression should not lead to wrap-around
 Control Flow
 52 (req): There shall be no unreachable code
 53 (req): All non-null statements shall have a side effect
 54 (req): A null statement shall only appear on a line by its self, and shall not have any other text on
 the same line
 55 (adv): Label should not be used except in switch statements
 56 (req): The goto statement shall not be used
 57 (req): The continue statement shall not be used
 58 (req): The break statement shall not be used, except to terminate the cases of a switch statement
 59 (req): The statements forming the body of an if, else if, else, while, do … while or for statement
 shall always be enclosed in braces
 60 (adv): All if, else if constructs should contain a final else clause
 61 (req): Every non-empty case clause in a switch statement shall be terminated with a break
 statement
 62 (req): All switch statements shall contain a final default clause
 63 (adv): A switch expression should not represent a Boolean value
 64 (req): Every switch statement should have at least one case
 65 (req): Floating point variables shall not be used as loop counters
 66 (adv): Only expression concerned with loop control should appear within a for statement
 67 (adv): Numeric variables being used within a for loop for iteration counting should not be
 modified in the body of the loop
 Functions
 68 (req): Functions shall always be declared at file scope
 69 (req): Functions with a variable number of arguments shall not be used
 70 (req): Functions shall not call themselves directly or indirectly
 71 (req): Functions shall always have prototype declarations and the prototype shall be visible at
 both the function definition and call
 72 (req): For each function parameter the type given and definition shall be identical, and the return
 type shall be identical73 (req): Identifiers shall either be given for all parameters in a prototype declaration, or none
 74 (req): If identifiers are given for any parameters, then the identifiers used in declaration and
 definition shall be identical
 75 (req): Every function shall have an explicit return type
 76 (req): Functions with no parameter list shall be declared with parameter type void
 77 (req): The unqualified type of parameters passed to a function shall be compatible with the
 unqualified expected types defined in the function prototype
 78 (req): The number of parameters passed to a function shall match the function prototype
 79 (req): The value returned by void functions shall not be used
 80 (req): Void expressions shall not be passed as function parameters
 81 (adv): const qualification should be used on function parameters that are passed by reference,
 where it is intended that the function will not modify the parameter
 82 (adv): A function should have a single exit point
 83 (req): For functions that do not have a void return type:
 i) There shall be one return statement for every exit branch (including the end of the
 program)
 ii) Each return shall have an expression
 iii) The return expression shall match the return type
 84 (req): For functions with void return type, return statements shall not have an expression
 85 (adv): Functions called with no parameters should have empty parentheses
 86 (adv): If a function returns error information then that information should be tested
 Pre-Processing Directives
 87 (req): #include statements in a file shall only be preceded by other pre-processor directives or
 comments
 88 (req): Non-standard characters shall not occur in header file names in #include directives
 89 (req): The #include directive shall be followed by either a <filename> of "filename" sequence
 90 (req): C macros shall only be used for symbolic constants, function like macros, type qualifiers
 and storage class specifiers
 91 (req): Macros shall not be #define'd and #undef'd within a block
 92 (adv): #undef should not be used
 93 (adv): A function should be used in preference to a function-like macro
 94 (req): A function-like macro shall not be 'called' without all of its arguments
 95 (req): Arguments to a function-like macro shall not contain tokens that look like pre-processor
 directives
 96 (req): In the definition of a function-like macro the whole definition, and each instance of a
 parameter, shall be enclosed in parenthesis
 97 (adv): Identifiers in pre-processor directives should be defined before use
 98 (req): There shall be at most one occurrence of the # or ## pre-processor operators in a single
 macro definition
 99 (req): All use of #pragma directive shall be documented and explained
 100 (req): The defined pre-processor operator shall only be used in one of the two standard formsPointers and Arrays
 101 (adv): Pointer arithmetic shall not be used
 102 (adv): No more than 2 levels of pointer indirection should be used
 103 (req): Relational operators shall not be applied to pointer types except where both operands are
 of the same type and point to the same array, structure or union
 104 (req): Non-constant pointers to functions shall not be used
 105 (req): All functions pointed to by a single pointer to a function shall be identical in the number
 and type of parameters and the return type
 106 (req): The address of an object with automatic storage shall not be assigned to an object which
 may persist after the object has ceased to exist
 107 (req): The null pointer shall not be dereferenced
 Structures and Unions
 108 (req): In the specification of a structure or union type, all members of the structure or union shall
 be fully specified
 109 (req): Overlapping variable storage shall not be used
 110 (req): Unions shall not be used to access the sub-parts of larger data types
 111 (req): Bit fields shall only be defined to be one of type unsigned int or signed int
 112 (req): Bit fields of type signed int shall be at least 2 bits long
 113 (req): All members of a structure or union shall be named and shall only be access with their
 name
 Standard Libraries
 114 (req): Reserved words and the standard library function names shall not be redefined or
 undefined
 115 (req): Standard library names shall not be reused
 116 (req): All libraries used in production code shall be written to comply with the provisions of
 "MISRA Guidelines for the use of the C language in vehicle based software", and shall
 have been subject to appropriate validation
 117 (req): The validity of values passed to library functions shall be checked
 118 (req): Dynamic heap memory allocation shall not be used
 119 (req): The error indicator errno shall not be used
 120 (req): The macro offsetof, in library <stddef.h>, shall not be used
 121 (req): <local.h> and the setlocale function shall not be used
 122 (req): The setjmp macro and the longjmp function shall not be used
 123 (req): The signal handling facilities of <signal.h> shall not be used
 124 (req): The input/output library <stdio.h> shall not be used in production code
 125 (req): The library functions atof, atoi and atol from library <stslib.h> shall not be used
 126 (req): The library functions abort, exit, getenv and system from library <stdlib.h> shall not be
 used
 127 (req): The time handling functions of library <time.h> shall not be used

授人以渔,不授人以鱼。
2013-08-10 21:53
快速回复:【转贴】MISRA-C:1998(解读)
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.042230 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved