BARR-C:2018 and MISRA C:2012: Synergy Between the Two Most Widely Used C Coding Standards

03/15/2020 ∙ by Roberto Bagnara, et al. ∙ 0

The Barr Group's Embedded C Coding Standard (BARR-C:2018, which originates from the 2009 Netrino's Embedded C Coding Standard) is, for coding standards used by the embedded system industry, second only in popularity to MISRA C. However, the choice between MISRA C:2012 and BARR-C:2018 needs not be a hard decision since they are complementary in two quite different ways. On the one hand, BARR-C:2018 has removed all the incompatibilities with respect to MISRA C:2012 that were present in the previous edition (BARR-C:2013). As a result, disregarding programming style, BARR-C:2018 defines a subset of C that, while preventing a significant number of programming errors, is larger than the one defined by MISRA C:2012. On the other hand, concerning programming style, whereas MISRA C leaves this to individual organizations, BARR-C:2018 defines a programming style aimed primarily at minimizing programming errors. As a result, BARR-C:2018 can be seen as a first, dramatically useful step to C language subsetting that is suitable for all kinds of projects; critical projects can then evolve toward MISRA C:2012 compliance smoothly while maintaining the BARR-C programming style. In this paper, we introduce BARR-C:2018, we describe its relationship with MISRA C:2012, and we discuss the parallel and serial adoption of the two coding standards.

READ FULL TEXT VIEW PDF
POST COMMENT

Comments

There are no comments yet.

Authors

page 1

page 4

This week in AI

Get the week's most popular data science and artificial intelligence research sent straight to your inbox every Saturday.

I Introduction

The C programming language is still, after half a century from its inception, among the most used programming languages overall111Source: TIOBE Index for December 2019, see https://www.tiobe.com/tiobe-index/. and the most used one for the development of embedded systems [1, 2]. The reasons for such success are deeply rooted in compelling industry requirements and have been discussed elsewhere (see, e.g., [3, 4]). Among such requirements are language size, stability and an evolution path that ensures backward compatibility.

Faithfulness of C to its original spirit is also a cause of problems. As discussed in [3, 4], each strong point of C comes with a corresponding weakness:

  • the ease of writing efficient compilers for almost any architecture, the existence of many compilers by different vendors and the fact that C is defined by an ISO standard are the reasons why the language is not fully defined;

  • the objective of easily obtaining efficient code with no hidden costs has been achieved, in C, also by ruling out all run-time error checking;

  • easy access to the hardware comes with the risk of inadvertently corrupt the program state;

  • language terseness opens the door to misunderstanding and abuse of the language that easily results into program that are obscure and unsuitable for code reviews.

The potential impact of the mentioned weak points of C is of course higher for critical applications. One of the pragmatic solutions adopted by industry to mitigate this problem is called language subsetting: critical applications are not programmed in unrestricted C, but in a subset where the potential of committing possibly dangerous mistakes is reduced. This is mandated or highly recommended by all functional safety standards, such as IEC 61508 [5] (industrial, generic), ISO 26262 [6] (automotive), CENELEC EN 50128 [7] (railways), RTCA DO-178B/C [8] (aerospace) and FDA’s General Principles of Software Validation [9] (medical devices).

Of course, coding in a safer subset of C is not enough to guarantee correctness. However:

  1. The restriction to a language subset where not fully defined behavior and problematic features are banned or severely regulated “can considerably help the efficiency and precision of the static analysis” [10]. In the case of C, the restrictions posed on features like unions, pointer casts and backward gotos can be exploited in the design of static analysis tools [3].

  2. Properly designed language subsets have a strong emphasis on code readability: code reviews combined with static analysis and the automatic enforcement of sound coding guidelines by means of high-quality tools are the basis of most effective defect removal strategies [11].

Concerning the second point, code readability is also influenced by coding practices that go beyond language subsetting (see, e.g., [12]). These have to do with code layout, naming of program entities, contents of source and header files, and use of comments.

A recent survey conducted among embedded system software professionals [1] found that, setting aside proprietary coding standards, MISRA C [13] is the most widely used coding standard, and BARR-C [14] is the next most widely used.222The survey described in [1] does not come with statistical significance guarantees, especially as far as the randomness of the surveyed group is concerned. However, we believe the sample size of 1,703 firmware designers is more than respectable and the survey findings are matched by the daily professional experience of the present authors. The survey found that, together, these coding standards were the primary basis of the project-specific coding standards followed by more than 40% of respondents.

BARR-C was not designed to compete against MISRA C: they are in fact compatible and complementary. In this paper, after a brief introduction of MISRA C:2012 [13], we introduce BARR-C:2018 [14] by highlighting its relationship with MISRA C:2012, and we discuss the parallel and serial adoption of the two coding standards.

The plan of the paper is the following: Section II recalls some well-known C language traps and pitfalls; Section III introduces the MISRA project and MISRA C; Section IV introduces BARR-C; Section V presents all the language-subsetting guidelines of BARR-C:2018 and their relationship with the MISRA C:2012 guidelines; Section VI presents all the stylistic guidelines of BARR-C:2018; Section VII presents scenarios for the successful adoption of both coding standards; Section VIII concludes.

Ii C Traps and Pitfalls

There are two main categories of issues that pose problems to the use of C in the development of critical systems:

  1. the language is not fully defined;

  2. the language can easily be abused to write obscure code that is resistant to reviewing activities.

We briefly review these categories in the following sections.

Ii-a C Is Not Fully Defined

In this paper we refer to the 1999 version of the ISO C standard [15], which is the latest version of the standard supported by MISRA C:2012 and BARR-C:2018. Nonetheless, the contents of this section applies to all versions of the ISO C standard.

For the reasons mentioned previously, the C standards leave several aspects of the language not fully defined. There are four classes of not fully defined behaviors

  • unspecified behavior where each implementation documents how the choice is made [15, Par. 3.4.1]; e.g., the sizes and precise representations of the standard integer types;

  • behavior that depends on local conventions of nationality, culture, and language that each implementation documents [15, Par. 3.4.2]; e.g., character sets and how characters, numbers, dates and times are displayed;

  • behavior, upon use of a non-portable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements [15, Par. 3.4.3]; e.g., attempting to write a string literal constant or shifting an expression by a negative number or by an amount greater than or equal to the width of the promoted expression;

  • use of an unspecified value, or other behavior where this International Standard provides two or more possibilities and imposes no further requirements on which is chosen in any instance [15, Par. 3.4.4]; e.g., the order in which actual parameters of function calls are evaluated.

In the sequel, we will collectively refer to these not fully defined behaviors as “non-definite behaviors.”

Setting aside locale-specific behavior, whose aim is to avoid some nontechnical obstacles to adoption, it is important to understand the intimate connection between non-definite behavior and the relative ease with which optimizing compilers can be written. In particular, C data types and operations can be directly mapped to data types and operations of the target machine. This is the reason why the sizes and precise representations of the standard integer types are implementation-defined: the implementation will define them in the most efficient way depending on properties of the target CPU registers, ALUs and memory hierarchy.

Overflow on signed integer types is undefined behavior because the C standard allows three different representations of signed integers: two’s complement, ones’ complement and sign-magnitude. For one’s complement and sign-magnitude, it is implementation-defined whether the negative zero bit pattern is a trap representation.333Trap representations are particular object representations that do not represent values of the object type. Simply reading a trap representation is undefined behavior. For instance, in a memory architecture with explicit parity bits or other error detection/correction codes, a representation with a faulty error detection/correction code can be a trap representation. The C compiler can thus assume signed integer overflow cannot happen and omit all checks for overflows.

Attempting to write on string literal constants is undefined behavior because they may reside in read-only memory and/or may be merged and shared: for example, a program containing "String" and "OtherString" may only store the latter and use a suffix of that representation to represent the former. So, if the hardware traps attempts to write read-only memory, an unspecified hardware exception may take place, otherwise the program might end up changing, due to sharing, more than one string literal. Again, the C compiler can thus assume the program will never try to write on a string literal constant.

The reason why shifting an expression by a negative number or by an amount greater than or equal to the width of the promoted expression is undefined behavior is due to two factors:

  1. Allowing shifting by a negative number of bit positions, an operation that is usually not supported in hardware, would require a test, a jump and a negation.

  2. Allowing shifting by an amount greater than or equal to the width of the promoted expression not only would be pointless: it would require extra machine instructions on those architectures where the shift count is reduced by masking in order to reduce the maximum execution time of the shift instructions. For instance, on IA-32 (Intel Architecture, 32-bit) only the 5 low-order bits are retained by a preliminary masking operation. As a result, shifting a 32-bit register to the left by 32 positions does not result in 0, as one would expect, but in the register being unchanged (the 5 low-order bits of 32 are 0, and shifting by 0 positions is a no-op).

So, for ease of implementation of the compiler and speed of the generated code, C leaves this behavior undefined.

If a program relies on undefined or unspecified behaviors, then its semantics is not defined, that is, it is not possible to assign any meaning to it. All programs do rely on implementation-defined behavior, so their semantics can be defined only with reference to the used implementation of the language [16]. Reliance on implementation-defined behavior is an obstacle both for portability and for understandability of the programs (there is such a variety of implementation-defined behaviors —112 in C99— that most of them are unknown to the majority of programmers).

Ii-B C Can Be Difficult To Read

There are many features of C that, if not properly used, can impact program readability and understandability:

  • the preprocessing phase;

  • a generous offer of operators with nontrivial and easily forgotten precedence and associativity rules;

  • a generous offer of control-flow mechanisms, some of which are characterized by a very complex semantics (goto, switch, for, break, continue, setjmp/longjmp, …);

  • implicit conversions governed by quite intricate rules;

  • two kinds of comment markers with a nontrivial interaction between themselves and with line splicing (i.e., splitting logical lines into multiple physical lines using trailing backslashes as line-continuation markers).

Remarkable examples of unreadable code are provided by the winners of The International Obfuscated C Code Contest, a contest running without interruption since 1984, which awards a prize to the most obscure/obfuscated C programs that respects a few basic rules.444http://www.ioccc.org/, last accessed on March 15, 2020.

As already mentioned, ensuring code readability and understandability is crucial for the effectiveness of code reviews and has an obvious impact on other program properties such as maintainability.

Iii Misra C

This paper is concerned with MISRA C:2012 [17]. This is the latest in a series of standards for the C language that have resulted from the MISRA project. Starting in 1990 with the mission of providing world-leading best practice guidelines for the safe and secure application of both embedded control systems and standalone software [4], the project published, in November 1994, “Development guidelines for vehicle based software” [18] prescribing the use of “a restricted subset of a standardized structured language.”

For this reason, the MISRA consortium began work on the MISRA C guidelines: at that time Ford and Land Rover were independently developing proprietary guidelines for vehicle-based C software and it was recognized that a common activity would be more beneficial to industry. The first version of the MISRA C guidelines was published in 1998 [19] and received significant industrial attention.

In 2004, MISRA published an improved version of the C guidelines [20] for which the intended audience was extended to include all industries that develop C software for use in high-integrity/critical systems. Due to the success of MISRA C and the fact that C++ is also used in critical contexts, in 2008, MISRA published a similar set of MISRA C++ guidelines [21].

Both MISRA C:1998 and MISRA C:2004 target the 1990 version of the C standard [22]. The latest version, MISRA C:2012, published in 2013 [17], supports both C99 [23] as well as C90 (in its amended and corrected form sometimes referred to as C95 [24]).555The MISRA C Working Group is currently working, among other things [25], at adding support for C11 [26] and C18 [27]. With respect to previous versions, MISRA C:2012 covers more language issues and provides a more precise specification of the guidelines with improved rationales and examples. MISRA C:2012 is the most authoritative language subset for the C programming language.

MISRA C, in its various versions, influenced all publicly-available coding standards for C and C++ that were developed after MISRA C:1998. Figure 1 shows part of the relationship and influence between the MISRA C/C++ guidelines and other sets of guidelines. It can be seen that MISRA C:1998 influenced Lockheed’s “JSF Air Vehicle C++ Coding Standards for the System Development and Demonstration Program” [28], which influenced MISRA C++:2008, which, in turn, influenced MISRA C:2012. The activity that led to MISRA C++:2008 was also encouraged by the UK Ministry of Defence which, as part of its Scientific Research Program, funded a work package that resulted in the development of a “vulnerabilities document” (the equivalent of Annex J listing the various behaviors in ISO C, which is missing in ISO C++, making it hard work to identify them and to ensure they are covered by the guidelines). Moreover, MISRA C deeply influenced NASA’s “JPL Institutional Coding Standard for the C Programming Language” [29] and several other coding standards (see, e.g., [30, 31]), including the BARR-C coding standards that will be described in the next sections [14].

Fig. 1: Origin and history of MISRA C and BARR-C

The MISRA C guidelines are concerned with aspects of C that impact on the safety and security of the systems, whether embedded or standalone: they define “a subset of the C language in which the opportunity to make mistakes is either removed or reduced” [17]. The guidelines ban critical non-definite behavior and constrain the use of implementation-defined behavior and compiler extensions. They also limit the use of language features that can easily be misused or misunderstood. Overall, the guidelines are designed to improve reliability, readability, portability and maintainability. We assume the reader has some general familiarity with MISRA C:2012 [13]: we recommend reading [4] if that is not the case.

There are two kinds of MISRA C guidelines:

  • a guideline where the information concerning compliance is not fully contained in the source code and requirements, specifications, design, etc., may have to be taken into account. Static analysis tools may be able to assist in checking compliance.

  • a guideline where information concerning compliance is fully contained in the source code. Discounting undecidability, static analysis tools should, in principle, be capable of checking compliance.

MISRA C has been designed to be used within the framework of a documented development process where justifiable non-compliances will be authorized and recorded as deviations. To facilitate this, each MISRA C guideline has been assigned a category.

  • C code that complies to MISRA C must comply with every mandatory guideline; deviation is not permitted.

  • C code that complies to MISRA C shall comply with every required guideline; a formal deviation is required where this is not the case.

  • these are recommendations that should be followed as far as is reasonably practical; formal deviation is not required, but non-compliances should be documented.666MISRA Compliance:2016 [32], which is optional for MISRA C:2012 but will become mandatory starting from the next version of MISRA C, allows these guidelines to be downgraded to “Disapplied”.

Every organization or project may choose to treat any required guideline as if it were mandatory and any advisory guideline as if it were required or mandatory.

Each MISRA C rule is marked as decidable or undecidable according to whether answering the question “Does this code comply?” can be done algorithmically. Rules are marked ‘decidable’ whenever compliance depends only on compile-time (static) properties such as the types of the objects or the names and the scopes of identifiers. Conversely, rules are marked ‘undecidable’ whenever violations depend on run-time (dynamic) properties such as the value contained in a modifiable object or whether control reaches a particular point.777Most interesting program properties such as whether a program can lead to a division by zero, a buffer overflow or a memory leak are undecidable. The majority of the MISRA C guidelines are decidable,888Out of a total of 173 guidelines, only 36 rules and 4 directives involve undecidable program properties [3]. and thus compliance can be checked by algorithms that:

  • do not need nontrivial approximations of the value of program objects;

  • do not need nontrivial control-flow information.

Of course, these algorithms can still be very complex. For instance, the nature of the translation process of the C language, which includes a preprocessing phase, is a source of complications: the preprocessing phase must be tracked precisely, and compliance may depend on the source code before preprocessing, on the source code after preprocessing, or on the relationship between the source code before and after preprocessing.

MISRA C rules are also classified as

single translation unit or system according to the amount of code that needs to be analyzed in order to check compliance. If a rule is marked ‘single translation unit’ then compliance can be determined by checking each translation unit independently. On the other hand, if a rule is marked ‘system’, then, to decide the compliance of code in a specific unit, all the source code in the program (or, in some cases, project) may need to be checked.

Iv BARR-C:2018: Introduction

The history of the Barr Group’s Embedded C Coding Standard —BARR-C for short— started with the publication, in 2009, of the Netrino’s Embedded C Coding Standard [33]. This coding standard, as well as its subsequent versions, was specifically designed to reduce the number of programming defects in embedded software as well as improving maintainability and portability. Netrino’s Embedded C Coding Standard was renamed Embedded C Coding Standard and released, in 2013, as a freely downloadable PDF document [34]. The next and current version, BARR-C:2018 [14] has been improved by ensuring that BARR-C’s guidelines can be combined with MISRA-C:2012’s guidelines without conflicts. Figure 1 shows the various versions of BARR-C in the larger context where they were developed.

As far as the compatibility between BARR-C:2018 and MISRA C:2012 is concerned, the objectives declared in [14] are:

  1. BARR-C-2018 guidelines that define a subset of the C programming language should never be more restrictive than the MISRA C:2012 guidelines. In other words, the subset of the C language defined by MISRA-C:2012 should itself be a subset of the subset defined by the BARR-C:2018 guidelines.

  2. BARR-C-2018 guidelines that place stylistic limitations on programmers (such as restricting code formatting or the names of some identifiers) do not contradict the MISRA C guidelines. In other words, BARR-C:2018 includes a C style guide that is complementary to MISRA C, which does not make any recommendations related purely to style.

As we will see in Section V-D, objective number 1 has not been fully achieved.

In compiling the BARR-C coding standard, guidelines were selected for their ability to minimize defects [14]:

When it was the case that one rule had the ability to prevent more defects from being made by programmers than an alternative rule for a similar aspect of coding, that more impactful rule was chosen. For example, the stylistic rules for when and where to place curly braces were selected on the basis of their ability to reduce bugs across a whole program.

BARR-C:2018 does not make a clear-cut distinction between guidelines such that information about compliance is in the code and the language implementation —rules in MISRA C parlance— and guidelines that require further information —directives in MISRA C:2012 [13]. The Enforcement section of each guideline description in BARR-C:2018 provides some indication about the use of (existing) tools and code reviews for compliance verification. In this paper, we adopt the MISRA C view in presenting BARR-C:2018. In particular:

  • we refer to generic BARR-C:2018 rules as “guidelines”;

  • we refer to BARR-C:2018 rules whose compliance only depends on the source code and the used language implementation as “rules”;

  • we refer to the remaining BARR-C:2018 rules as “directives”.

BARR-C:2018 guidelines will be introduced using the following format:

  • Headline (relationship with MISRA C:2012, if any)

where

  • C, S and I are the chapter, section and item letter that uniquely identify the guideline;

  • G is either D, for directives, or R, for rules;

  • the optional symbol flags guidelines that, according to [14], are objectively expected to reduce the number of defects (38 out of 143 guidelines of BARR-C:2018 are marked as such);

  • the optional ! symbols flags guidelines that are dubbed “bug-killing” in [35];999While [35] mentions 10 rules, one of them, “Rule #5” in [35] is the combination of guidelines 2.1.b and 2.1.c of [14]. There are thus 11 !-tagged guidelines in the present paper.

  • headline is a brief summary of the guideline.

Please note that in several cases the headline has been conceived just for this paper and for illustrative purposes only: the reader should check the real, full guideline text in [14].

All but 5 BARR-C:2018 rules can be checked at the level of the single translation unit: the exceptions are 1.8.a, 1.8.b, 4.2.c, 7.2.a, and 8.4.b. All but 3 of them are decidable: the exceptions are 1.8.b, 7.2.a, and 8.4.b.

V BARR-C:2018 Language Subsetting Guidelines

In this section we present the language subsetting guidelines in BARR-C:2018. We have 64 such guidelines (out of 143), which we divide into four categories:

  1. guidelines with an exact match in MISRA C:2012;

  2. guidelines with a non-exact match in MISRA C:2012;

  3. guidelines with related guidelines in MISRA C:2012;

  4. guidelines without correspondence in MISRA C:2012.

Each category is introduced in the four following sections.

V-a BARR-C:2018 Guidelines with an Exact Match in MISRA C:2012

10 guidelines of BARR-C:2018 have an (almost) exact match in MISRA C:2012. They are:

  • Do not use preprocessor directive #define to define macros with the same name as a keyword (MISRA C:2012 Rule 20.4).

  • Do not rely on C’s operator precedence rules (MISRA C:2012 Rule 12.1).

  • All declarations and definitions of variables or functions at file scope must have internal linkage unless external linkage is required (MISRA C:2012 Rule 8.7).

  • Code shall never be commented out (MISRA C:2012 Dir 4.4).

  • There must be only one return statement exiting a function and this must be at the end of the function (MISRA C:2012 Rule 15.5).101010This guideline is controversial, but the single point of exit is explicitly required by IEC 61508 [5] and ISO 26262 [6].

  • Any object or function declaration or definition with internal linkage must include the static storage class specifier (MISRA C:2012 Rule 8.8).

  • Each parameter shall be explicitly declared and meaningfully named (MISRA C:2012 Rule 8.2).

  • Use function-like macros only when they are not replaceable by (inline) function calls (MISRA C:2012 Dir 4.9).

  • All variables shall be initialized before use (MISRA C:2012 Rule 9.1).

  • Any if statement with an else if clause shall end with an else clause (MISRA C:2012 Rule 15.7).

V-B BARR-C:2018 Guidelines with a Non-Exact Match in MISRA C:2012

27 guidelines of BARR-C:2018 have a non-exact match in MISRA C:2012. They are:

  • All programs shall be written to comply with the C99 version of the ISO C Programming Language Standard (MISRA C:2012 Rule 1.1). The MISRA guideline is less restrictive in that it allows also C90.

  • Whenever a C++ compiler is used, appropriate compiler options shall be set to restrict the language to the selected version of ISO C (MISRA C:2012 Rule 1.1).

  • Use the typedefs provided by <stdint.h> instead of the basic integer types (MISRA C:2012 Dir 4.6). The MISRA guideline is more general in that: it covers also the floating-point types; it covers also C90, for which it allows the use of type names different from those provided by <stdint.h>.

  • Braces shall always surround the bodies of if, else, switch, while, do, and for (MISRA C:2012 Rule 15.6, for iteration and selection statements, and Rule 16.1, for switch statements).

  • Possibly avoid all uses of the goto keyword. If goto is used it shall only jump to a label declared later in the same or an enclosing block (MISRA C:2012 Rule 15.1, advisory ban of goto, and Rule 15.2, required limitation to forward jumps).

  • The const keyword shall be used whenever appropriate (MISRA C:2012 Rule 8.13, advisory restriction to const-qualified pointees).

  • Comments shall never contain the preprocessor tokens /*, //, or \ (MISRA C:2012 Rule 3.1 covers /* and //, Rule 3.2 covers \).

  • Each header file shall contain a preprocessor guard against multiple inclusion. (MISRA C:2012 Dir 4.10, except that BARR-C:2018 Rule 4.2.b also requires a comment after the closing #endif).

  • Bit-fields shall not be defined within signed integer types (MISRA C:2012 Rule 6.1 allows bitfields that are explicitly signed/unsigned).

  • None of the bitwise operators (i.e., &, |, ~, ^, <<, and >>) shall be used to manipulate signed integer data (MISRA C:2012 Rule 10.1 covers more than bitwise operators and conditions are more general).

  • Signed integers shall not be combined with unsigned integers in comparisons or expressions. In support of this, decimal constants meant to be unsigned should be declared with a ‘u suffix (MISRA C:2012 Rule 10.4 covers the first part of this rule, MISRA C:2012 Rule 7.2 covers the second part).

  • No procedure shall have a name that is a keyword of any standard version of the C or C++ programming language (MISRA C:2012 Rule 21.2 covers only the keywords of the applicable C standard).

  • No procedure shall have a name that overlaps a function in the C Standard Library (MISRA C:2012 Rule 21.2 covers all kinds of identifiers and macro names, not just function names).

  • No procedure shall have a name that begins with an underscore (MISRA C:2012 Rule 21.2 prevents declaration of any identifier with a reserved name, and this includes those beginning with underscore).

  • No procedure name shall be longer than 31 characters (MISRA C:2012 Rule 5.1 requires external identifiers to be distinct which, for a generic C99 compiler, implies different external procedure names shall differ in the first 31 characters).

  • A prototype shall be declared for each public function in the module header file (MISRA C:2012 Rule 8.5 covers this rule, but it applies also to objects and requires one and only one declaration per function/object).

  • If parameterized macros are used, the following restrictions apply: (i) macro body surrounded in parentheses; (ii) macro parameters surrounded in parentheses; (iii) macro parameters used no more than once; (iv) do not include control transfer statements (MISRA C:2012 Rule 20.7 covers the same issues addressed by points i and ii; points iii and iv are not covered by MISRA C:2012).

  • No variable shall have a name that is a keyword of C, C++, or any other well-known extension of the C programming language, including specifically K&R C and C99. (MISRA C:2012 Rule 21.2 covers only the keywords of the applicable C standard).

  • No variable shall have a name that overlaps with a variable name from the C Standard Library (MISRA C:2012 Rule 21.2 is more general).

  • No variable shall have a name that begins with an underscore (MISRA C:2012 Rule 21.2 prevents declaration of any identifier with a reserved name, and this includes those beginning with underscore).

  • No variable name shall be longer than 31 characters (MISRA C:2012 Rule 5.1 requires external identifiers to be distinct, which, for a generic C99 compiler, implies different external variable names shall differ in the first 31 characters).

  • All switch statements shall contain a default block (MISRA C:2012 Rule 16.5 prescribes presence and positioning of the the default label).

  • Any case designed to fall through to the next shall be commented to clearly explain the absence of the corresponding break (MISRA C:2012 Rule 16.3 requires presence of the final break apart from the case of consecutive labels).

  • With the exception of the initialization of a loop counter in the first clause of a for statement and the change to the same variable in the third, no assignment shall be made in any loop’s controlling expression (MISRA C:2012 Rule 14.2 covers this rule, but is more general).

  • Infinite loops shall be implemented via controlling expression for (;;) (MISRA C:2012 Rule 14.2 allows for (;;) specifically for the purpose of expressing infinite loops).

  • The use of goto statements shall be restricted as per rule 1.7.c (MISRA C:2012 Rule 15.1, advisory ban of goto, and Rule 15.2, required limitation to forward jumps).

  • C Standard Library functions abort(), exit(), setjmp(), and longjmp() shall not be used (MISRA C:2012 Rule 21.8 bans abort(), exit() and other functions of <stdlib.h>, MISRA C:2012 Rule 21.4 bans all uses of <setjmp.h>, including setjmp() and longjmp()).

V-C BARR-C:2018 Guidelines with Related Guidelines in MISRA C:2012

10 guidelines of BARR-C:2018 have related, though not matching, counterpart in MISRA C:2012. They are:

  • Minimize the use of proprietary compiler language keyword extensions, #pragma, and inline assembly (MISRA C:2012 Rule 1.2 advises not to use language extensions; Dir 1.1 requires to document all relevant implementation-defined behaviors including those provided via new keywords and #pragma directives; Dir 4.3 requires to encapsulate and isolate inline assembly code; Dir 4.2 advises to document all usage of assembly language).

  • Unless it is a single identifier or constant, each operand of the && and || operators shall be surrounded by parentheses (compliance with this rule contributes to compliance with MISRA C:2012 Rule 12.1).

  • The header file shall identify only the procedures, constants, and data types (via prototypes or macros, #define, and typedefs, respectively) about which it is strictly necessary for other modules to be informed (MISRA C:2012 Dir 4.8 advises the use of opaque pointers for pointers to structures or unions that are never dereferenced within a translation unit).

  • Use of the keyword char shall be restricted to the declaration of and operations concerning strings (MISRA C:2012 Rules 10.1, 10.2, and 10.4 restrict the use of plain char objects to the representation of characters and strings).

  • When floating point calculations are necessary: (i) Use the C99 type names float32_t, float64_t, and float128_t. (ii) Append an ‘f’ to all single-precision constants. (iii) Ensure that the compiler supports double precision, if your math depends on it. (iv) Never test for equality or inequality of floating point values. (v) Always invoke the isfinite() macro to check that prior calculations have resulted in neither INFINITY nor NAN. (MISRA C:2012 Dir 4.6 covers point i, Dir 1.1 covers point iii).

  • Appropriate care shall be taken to prevent the compiler from inserting padding bytes within

    struct or union types used to communicate to or from a peripheral or over a bus or network to another processor. (MISRA C:2012 Rule 19.2 advises not to use union, Dir 1.1 requires to document all relevant implementation-defined behaviors, including those involving padding bytes).

  • Boolean variables shall be declared as type bool (MISRA C:2012 Rule 10.1 prevents uses of non-Booleans in Boolean-expecting contexts; MISRA C:2012 also recommends using <stdbool.h> when available [13, Appendix D.6.4]).

  • Non-Boolean values shall be converted to Boolean via use of relational operators (e.g., < or !=), not via casts (MISRA C:2012 Rule 10.5 bans casting to Booleans, among other type casts).

  • Assignments shall not be made within an if or else if test (MISRA C:2012 Rule 13.4 advises not to use the result of assignment operators in any way; MISRA C:2012 Rule 14.4 requires the controlling expression of if statements to have Boolean type).

  • Each loop with an empty body shall feature a set of braces enclosing a comment to explain why nothing needs to be done until after the loop terminates (MISRA C:2012 Rule 15.6 requires the braces but not the comment).

V-D BARR-C:2018 Guidelines without Correspondence in MISRA C:2012

17 guidelines of BARR-C:2018 are not stylistic and have no counterpart in MISRA C:2012. The fact that this category is not empty, strictly speaking, implies that the objective of making the BARR-C subset of C a superset of MISRA C:2012 has not been achieved by BARR-C:2018. In order to fully understand the matter, it helps to divide this category into further subcategories:

V-D1 Ban on Obsolete Keywords

  • The auto keyword shall not be used.

  • The register keyword shall not be used.

The auto keyword is only in the language for historical reasons, as it serves no useful purpose. To the contrary, it may be used to declare implicit int variables with declarations like auto x. While this violates a constraint of C99 [15, Section 6.7] (and thus Rule 1.1.a of BARR-C:2018 and Rule 1.1 of MISRA C:2012), many compilers still generate code for that, with or without producing a warning. Implicit int for C90 is banned by Rule 8.1 of MISRA C:2012. Summarizing, the only good reason to keep auto in a C subset is to accommodate legacy code.

The register keyword is also in the language for historical reasons: since at least a couple of decades, compilers are much better than humans in deciding which variables should be allocated to registers taking into account the registers supply of the target processor. It shares with auto the disadvantage of allowing implicit int declarations like in register x. The only potentially interesting use case of register is in preventing the taking of addresses of automatic variables: the declaration register float y does not allow the address of y to be taken. This could help in preventing undefined behavior caused by dangling references: while MISRA C:2012 has Rule 18.6 to prevent them,111111“The address of an object with automatic storage shall not be copied to another object that persists after the first object has ceased to exist” [13, Rule 18.6]. BARR-C has no guidelines to mitigate this risk.

V-D2 Development Process

  • A set of templates for header files and source files shall be maintained at the project level.

  • Appropriate care shall be taken to prevent the compiler from altering the intended order of the bits within bit-fields.

  • The compiler must be informed that the function is an ISR by way of a #pragma or compiler-specific keyword, such as “__interrupt”.

  • Ensure that ISRs are not inadvertently called from other parts of the software.

  • A stub or default ISR shall be installed in the vector table at the location of all unexpected or otherwise unhandled interrupt sources; each such stub could attempt to disable future interrupts of the same type.

These are prescriptions on the development process: when the compiler does support them, they require the use language extensions. As such, they are not strictly related to language subsetting.

V-D3 Definite Language Subsetting Guidelines

  • It is a preferred practice to avoid all use of the continue keyword.

  • The volatile keyword shall be used whenever appropriate.

  • There shall always be precisely one header file for each source file and they shall always have the same root name.

  • No public header file shall contain a #include of any private header file.

  • The keywords short and long shall not be used.

  • Avoid the use of floating point constants and variables whenever possible.

  • Any pointer variable lacking an initial address shall be initialized to NULL.

  • Magic numbers shall not be used as the initial value or in the endpoint test of a while, dowhile, or for loop.

  • A declaration shall not declare more than one declarator.121212BARR-C:2018 [14] wording erroneously mentions the comma operator (which is a different thing) not to be used within variable declarations. The intention, however, is clearly the one to avoid +char * x, y+ as well as +int *f(void), g(int z)+.

  • Nested ifelse statements shall not be deeper than two levels.

Concerning 1.7.d, the continue statement was banned by Rule 14.5 of MISRA C:2004 [20]; it is allowed without restrictions in MISRA C:2012. For 1.8.c, casts removing const or volatile qualification are banned by MISRA C:2012 Rule 11.8; omitting the volatile

qualification is a source of bugs that may be very difficult to diagnose. Regarding the advice of 5.4.a not to use floating point constants and variables unless necessary, MISRA C:2012 Dir 1.1 requires documentation and understanding of, among other things, the many implementation-defined aspects of floating point arithmetic, when used. Finally, the lack of a guideline in MISRA C:2012 that, similarly to BARR-C:2018’s 8.1.a, recommends against having more than one declarator per declaration, is probably due to an oversight.

Vi BARR-C:2018 Stylistic Guidelines

The matter of style, while being essential to ensure program readability, is highly subjective. Everyone in software development knows that matters apparently as futile as the “right” indent size has the potential of causing friction within the development team. Nonetheless, as observed in [14], “[individual] programmers do not own the software they write. All software development is work for hire for an employer or a client […]”. So, someone has to make stylistic choices and consistency is usually much more important than the details of the chosen rules. Readers interested in programming style are referred to the classic The Elements of Programming Style [36], published in 1978 with examples in PL/I and Fortran, but still a source of good advice, which is largely independent from the programming language.

79 out of 143 guidelines of BARR-C:2018 [14] are stylistic in nature. They cover guidance on line width, horizontal spacing (blanks spaces, tabs, alignment, indentation), vertical spacing (new-line and other control characters), further code layout issues, naming (modules and files, types, functions variables), language, comments, and source file contents. They are illustrated in the following sections.

Vi-a Line Width Guidance

BARR-C:2018 has one rule concerning the maximum line width for program sources.

  • Limit the length of all lines in a program to a maximum of 80 characters.

The rationale for this rule is to increase readability. While the limitation to 80 characters originates from the width of IBM punch cards and 80-column-wide screens, very long lines are difficult to read on a computer screen [37]. Longer lines might be broken by the editor in ways that impair reading further or, worse, the final part of the line might be shown in a way that escapes the reader’s attention.

Code reviews can benefit from the availability of high-quality printed listings, which are usually limited to 65–70 characters per line, depending on the font and paper size. For maximum readability, the majority of program text should fit into 55 characters [38]. Depending on the technology used to obtain the printed listing, the final part of long lines may simply be not printed.

Vi-B Horizontal Spacing Guidance

It is well known that the systematic use of horizontal space helps readability. A balance has to be found between opposite goals: keep things separated enough to avoid clutter, keep them close enough to convey the connection between them; indent enough to make inclusions noticeable, but not too much to avoid long lines or line splits; aligning can improve readability, but overdoing it might impair readability.

Vi-B1 Blank Spaces Guidance

BARR-C:2018 has 13 rules concerning the presence or absence of blank spaces, namely:

  • Use one space after the keywords if, while, for, switch, and return.

  • Use one space before and after assignment operators =, +=, -=, *=, /=, %=, &=, |=, ^=, ~=, and !=.

  • Use one space before and after binary operators +, -, *, /, %, <, <=, >, >=, ==,!=, <<, >>, &, |, ^, &&, and ||.

  • Use no space on the operand side for unary operators +, -, ++, --, !, and ~.

  • Use one space before and after pointer operators * and & in declarations, no space on the operand side in other contexts.

  • Use one space before and after ? and : characters comprising the ternary operator.

  • Use no spaces around the structure pointer (->) and structure member (.) operators.

  • Use no spaces around square brackets of the array subscript operator [] unless required by another rule.

  • Use no spaces after ( or before ) in expressions.

  • Use no spaces around ( and ) in function calls, one space between the function name and ( in function definitions.131313BARR-C-2018 says declarations but such space is not present in the non-defining function declarations presented in crc.h [14, Appendix D].

  • Use one space after each comma separating function parameters.

  • Use one space after each semicolon separating the for statement clauses.

  • Use no space before the semicolon terminating a statement.

Vi-B2 Tab Guidance

  • Do not use the tab character (ASCII HT, 0x09).

Tab cannot be expected to be consistently set across editors and browsers. In addition, mixing tabs and spaces is problematic as far as searches and substitutions are concerned.

Vi-B3 Alignment Guidance

BARR-C:2018 has 5 rules concerning alignments that, emphasizing similarity, improve readability:

  • Align names of variables within a series of declarations.

  • Align names of struct and union members.

  • Align assignment operators within a block of adjacent assignment statements.

  • Align the leading # in preprocessor directives

  • The break for each case shall be indented to align with the associated case.

Vi-B4 Indentation Guidance

BARR-C:2018 has 2 rules and 1 directive concerning indentation, namely:

  • Use 4 character per indentation level.

  • Case labels shall be aligned and the contents of each case block shall be indented once from there.

  • When long lines are broken into multiple lines, use indentation to maximize readability.

The directive recommends to choose the breaking point wisely, e.g., to facilitate the interpretation of logical source lines of code containing operators, and to use indentation to emphasize the continuation context.

Vi-C Vertical Spacing Guidance

Vi-C1 New-lines Guidance

BARR-C:2018 has 3 rules concerning the use of new-line characters to increase readability, namely:

  • Write at most one statement per line.

  • A blank line shall precede each natural block of code (loops, conditionals, switches, consecutive declarations).

  • Each source file shall be terminated by a comment marking the end of file followed by a blank line.

It is worthwhile noting that rule 3.3.c also avoids a case of undefined behavior: this happens when a source file that is not empty does not end in a new-line character [15, 5.1.1.2p2].

Vi-C2 Control Characters Guidance

Given that the horizontal tab HT is forbidden by rule 3.5.a, very few ASCII control character are allowed by [14]:

  • End source code lines with LF (ASCII 0x0A), not with the pair CR-LF (ASCII 0x0D 0x0A).

  • Do not use other control characters apart from the form feed character FF (ASCII 0x0C).

  • Whenever possible, all functions shall be made to start at the top of a printed page, except when several small functions can fit onto a single page.

Vi-D Mixed Code Layout Guidance

  • Blocks shall be delimited by a left brace ({) alone in the line and a right brace (}) alone in the line and in the same column as the left brace.

  • All reasonable effort shall be taken to keep the length of each function limited to one printed page, or a maximum of 100 lines.

  • Define local variables as you need them, rather than all at the top of a function.

  • If project- or file-global variables are used, their definitions shall be grouped together and placed at the top of a source code file.

  • It is a preferred practice that the shortest (measured in lines of code) of the if and else if clauses should be placed first.

  • When evaluating the equality of a variable against a constant, the constant shall always be placed to the left of the equal-to operator (==).

Vi-E Naming Guidance

One of the crucial activities in software development is choosing the right names. The interested reader can find detailed guidance on naming in [39] and [40, p. 104 ff.].

Vi-E1 Module and File Names

In [14] a module is a logical entity with a name. A module is implemented in one header file and one source file.

  • Module names shall consist entirely of lowercase letters, numbers, and underscores.

  • Module names shall be unique in their first 8 characters and end with suffices .h and .c for the header and source file names, respectively.

  • No module’s header file name shall share the name of a header file from the C or C++ standard libraries.

  • Modules containing a main() function shall have the word “main” as part of their source file name.

Vi-E2 Type Names

  • The names of all new data types, including structures, unions, and enumerations, shall consist only of lowercase characters and internal underscores and end with _t.

  • All new structures, unions, and enumerations shall be named via a typedef.

  • The name of all public data types shall be prefixed with their module name and an underscore.

Vi-E3 Function Names

  • No function name shall contain any uppercase letters.

  • No macro name shall contain any lowercase letters.

  • Underscores shall be used to separate words in procedure names.

  • Each procedure’s name shall be descriptive of its purpose.

  • The names of all public functions shall be prefixed with their module name and an underscore (e.g., sensor_read()).

  • All functions that encapsulate threads of execution (a.k.a., tasks, processes) shall be given names ending with “_thread” (or “_task”, “_process”).

  • All functions that implement ISRs shall be given names ending with “_isr”.

Vi-E4 Variable Names

  • No variable name shall be shorter than 3 characters.

  • No variable name shall contain any uppercase letters.

  • No variable name shall contain any numeric value that is called out elsewhere.

  • Underscores shall be used to separate words in variable names.

  • Each variable’s name shall be descriptive of its purpose.

  • The names of any global variables shall begin with the letter ‘g’.

  • The names of any pointer variables shall begin with the letter ‘p’.

  • The names of any pointer-to-pointer variables shall begin with the letters ‘pp’.

  • The names of all integer variables containing Boolean information (including 0 vs. non-zero) shall begin with the letter ‘b’ and phrased as the question they answer.

  • The names of any variables representing non-pointer handles for objects, e.g., file handles, shall begin with the letter ‘h’.

  • In the case of a variable name requiring multiple of the above prefixes, the order of their inclusion before the first underscore shall be [g][p|pp][b|h].

Vi-F Language Guidance

  • Use only common and widely understood abbreviations and acronyms.

  • Maintain a project-specific table of abbreviations and acronyms.

Vi-G Comment Guidance

  • comment each cast describing how the code ensures proper behavior.

  • Single-line comments in the C++ style (i.e., preceded by //) are a useful and acceptable alternative to traditional C style comments (i.e., /**/).

  • All comments shall be written in clear and complete sentences, with proper spelling and grammar and appropriate punctuation.

  • The most useful comments generally precede a block of code that performs one step of a larger algorithm.

  • Avoid explaining the obvious.

  • The number and length of individual comment blocks shall be proportional to the complexity of the code they describe.

  • Whenever a comment references an external document, the comment shall include sufficient references to the original source.

  • Whenever a flow chart or other diagram is needed to sufficiently document the code, the drawing shall be maintained with the source code under version control and the comments should reference the diagram by file name or title.

  • All assumptions shall be spelled out in comments.

  • Each module and function shall be commented in a manner suitable for automatic documentation generation, e.g., via Doxygen.

  • Use the following capitalized comment markers to highlight important issues: (i) “WARNING:” alerts a maintainer there is risk in changing this code. (ii) “NOTE:” provides descriptive comments about the “why” of a chunk of code—as distinguished from the “how” usually placed in comments. (iii) “TODO:” indicates an area of the code is still under construction and explains what remains to be done.

Vi-H Source File Contents Guidance

  • Each source file shall include only the behaviors appropriate to control one “entity”.

  • Each source file shall be comprised of some or all of the following sections, in the order listed: comment block; include statements; data type, constant, and macro definitions; static data declarations; private function prototypes; public function bodies; then private function bodies.

  • Each source file shall always #include the header file of the same name (e.g., file adc.c should #include "adc.h"), to allow the compiler to confirm that each public function and its prototype match.

  • Absolute paths shall not be used in include file names.

  • Each source file shall be free of unused include files.

  • No source file shall #include another source file.

Vii Adoption of BARR-C:2018 and MISRA C:2012

Given the substantial compatibility of BARR-C:2018 and MISRA C:2012, they can both be applied, at least partially. They have in common least a few important characteristics:

  1. they are established and rather well known in the embedded systems’ community (even though MISRA C predates BARR-C of more than a decade):

  2. they have both been designed with static analysis in mind (even though the MISRA C:2012 guidelines are more precisely specified than the BARR-C:2018 ones);

  3. they both support a deviation process.

For safety-related projects, the adoption of the stylistic subset of BARR-C:2018 can be part of complying with the spirit of MISRA C:2012. In fact [13, Section 5.2.2, Process activities expected by MISRA C]:

It is recognized that a consistent style assists programmers in understanding code written by others. However, since style is a matter for individual organizations, MISRA C does not make any recommendations related purely to programming style. It is expected that local style guides will be developed and used as part of the software development process.

While the stylistic guidance provided by BARR-C:2018 may not suit the taste of everyone, the fact that it exists, is publicly available, and is supported by tools is a strong point in its favor. Another aspect to be taken into account is that BARR-C:2018 is flexible as far as quantities are concerned [14, Deviation Procedure]:

At the project level, rules that indicate a specific quantity of something (e.g., the number of characters per indent or maximum lines in a function) can be changed to enforce a different quantity that works better in the actual development tools. The specific quantity is not typically the key property of these types of rules.

There is another important way in which BARR-C and MISRA C can coexist: by providing a smooth entry path for organizations and projects that do not have (yet) or only have partial requirements about MISRA C compliance. In fact, BARR-C:2018 fills an important gap: there is way too much C software that, in the absence of normative or contractual obligations to comply with mature coding standards such as the MISRA ones, is developed in unconstrained C and not subjected to any static analysis. For such projects, moving from the wild to (partial) compliance with BARR-C:2018 would constitute an important step forward, and one that is not toot difficult to make. The further step would be, at least for the critical project, to move from BARR-C:2018 compliance to MISRA C:2012 compliance. This step would be significantly easier to take, compared to the case where the starting point is “no coding standard, no static analysis.” For a least two reasons:

  1. Culture: a team already trained to the use of coding standards and static analysis can more easily move to a more complex coding standard and static analyses.

  2. Starting point: part of the work required to comply with MISRA C:2012 has already been done by complying to BARR-C:2018.

A project that is compliant with BARR-C:2018 will be mostly compliant with 22 MISRA C:2012 guidelines. These are:141414Mandatory MISRA C:2012 guidelines are set in boldface, advisory ones in italics. Dir 4.4 (by 2.1.c), Dir 4.6 (by 5.2.a and 5.4.b), Dir 4.9 (by 6.3.a), Dir 4.10 (by 4.2.b), Rule 1.1 (by 1.1.a and 1.1.b), Rule 3.1 (by 2.1.b), Rule 3.2 (by 2.1.b), Rule 6.1 (by 5.3.a), Rule 7.2 (by 5.3.c), Rule 8.2 (by 6.2.f), Rule 8.7 (by 1.8.a), Rule 8.8 (by 6.2.e), Rule 8.13 (by 1.8.b), Rule 9.1 (by 7.2.a. Rule 12.1 (by 1.4.a), Rule 15.1 (by 1.7.c or 8.5.a),151515The BARR-C:2018 goto rules cover both MISRA C:2012 Rule 15.1 and Rule 15.2 if no gotos are allowed but only Rule 15.2 if forward gotos are allowed. Rule 15.2 (by 1.7.c or 8.5.a),161616See footnote 15. Rule 15.5 (by 6.2.c), Rule 15.6 (by 1.3.a), Rule 15.7 (by 8.2.d), Rule 20.4 (by 1.1.d), Rule 20.7 (by 6.3.b.

In addition, the same project will be partially compliant to the following 19 guidelines: Dir 1.1 (by 1.1.c), Dir 4.2 (by 1.1.c), Dir 4.3 (by 1.1.c), Dir 4.8 (by 4.2.c), Rule 1.2 (by 1.1.c), Rule 5.1 (by 6.1.d and 7.1.d), Rule 8.5 (by 6.2.d), Rule 10.1 (by 5.2.c and 5.3.b 5.6.a), Rule 10.2 (by 5.2.c), Rule 10.4 (by 5.2.c and 5.3.c), Rule 10.5 (by 5.6.b), Rule 13.4 (by 8.2.c), Rule 14.2 (by 8.4.b and 8.4.c), Rule 16.1 (by 1.3.a), Rule 16.5 (by 8.3.b), Rule 19.2 (by 5.5.a), Rule 21.2 (by 6.1.a), 6.1.b), 6.1.c and 7.1.a), Rule 21.4 (by 8.5.b), Rule 21.8 (by 8.5.b).

Passing from BARR-C:2018 compliance to MISRA C:2012 compliance requires taking into account 9 further directives (7 required and 2 advisory) and 123 further MISRA C:2012 rules (13 mandatory, 87 required and 23 advisory). Such guidelines are listed in the following, divided into broad categories.

Vii-a Prevention of undefined and unspecified behavior

This category contains 5 directives and 61 rules: Dir 2.1, Dir 4.1, Dir 4.11, Dir 4.12, Dir 4.14, Rule 1.3, Rule 5.2, Rule 5.4, Rule 7.4, Rule 8.6, Rule 8.3, Rule 8.4, Rule 8.10, Rule 8.14, Rule 9.2, Rule 9.4, Rule 10.3, Rule 11.1, Rule 11.2, Rule 11.3, Rule 11.4, Rule 11.5, Rule 11.6, Rule 11.7, Rule 11.8, Rule 12.2, Rule 13.1, Rule 13.2, Rule 13.3, Rule 13.6, Rule 17.1, Rule 17.3, Rule 17.4, Rule 17.6, Rule 18.1, Rule 18.2, Rule 18.3, Rule 18.6, Rule 18.7, Rule 18.8, Rule 19.1, Rule 20.1, Rule 20.2, Rule 20.3, Rule 20.6, Rule 20.10, Rule 20.11, Rule 21.1, Rule 21.3, Rule 21.5, Rule 21.6, Rule 21.7, Rule 21.9, Rule 21.10, Rule 21.11, Rule 21.12, Rule 21.13, Rule 21.14, Rule 21.16, Rule 21.17, Rule 21.18, Rule 21.19, Rule 22.2, Rule 22.4, Rule 22.5, Rule 22.6.

Vii-B Limiting dependence on implementation-defined behavior

The following 2 rules help with program portability by avoiding some implementation-defined behaviors: Rule 4.1, Rule 22.3.

Vii-C Enhancing readability

There are 1 directive and 21 rules in this category: Dir 4.5 Rule 2.3, Rule 2.4, Rule 2.5, Rule 2.6, Rule 2.7, Rule 4.2, Rule 5.3, Rule 7.3, Rule 8.9, Rule 8.12, Rule 9.3, Rule 9.5, Rule 11.9, Rule 12.3, Rule 15.4, Rule 16.2, Rule 16.6, Rule 16.7, Rule 18.5, Rule 20.5, Rule 20.14.

Vii-D Enhancing verifiability

These guidelines help the analysis and verifiability of the source code. There are 1 such directive and 5 rules: Dir 4.13, Rule 8.11, Rule 15.3, Rule 16.4, Rule 17.5, Rule 17.7.

Vii-E Reducing developer confusion

These 25 rules avoid code that may lead to developer confusion: Rule 2.1, Rule 2.2, Rule 5.5, Rule 5.6, Rule 5.7, Rule 5.8, Rule 5.9, Rule 6.2, Rule 7.1, Rule 8.1, Rule 10.6, Rule 10.7, Rule 10.8, Rule 12.4, Rule 12.5, Rule 13.5, Rule 14.4, Rule 16.3, Rule 17.8, Rule 18.4, Rule 20.8, Rule 20.9, Rule 20.12, Rule 20.13, Rule 21.15.

Vii-F Prevention of unexpected run-time behavior

These guidelines help prevent run-time failures and unexpected results. These are 2 directives and 9 rules in this category: Dir 3.1, Dir 4.7, Rule 14.1, Rule 14.3, Rule 17.2, Rule 21.20, Rule 22.1, Rule 22.7, Rule 22.8, Rule 22.9, Rule 22.10.

Viii Conclusion

In this paper we have illustrated the connections between the two most widely used coding standards in the embedded systems industry: MISRA C and BARR-C. We have briefly recalled some of the advantages and disadvantages of using the C programming language for embedded systems and how its uncontrolled use is not adequate for the development of systems that are even moderately critical. We have also summarized the background, motivation and history of the MISRA project and of MISRA C in particular.

After recalling the main features of the MISRA C:2012 guidelines, we have introduced the BARR-C:2018 coding standard from the MISRA point of view. All BARR-C:2018 guidelines have been presented, divided into two broad categories: those dealing with language subsetting and project management, and those concerning programming style. The BARR-C:2018 guidelines in the first category have been further classified on the basis of their overlap with the MISRA C:2012 guidelines. Those in the second category have been further classified into subcategories of stylistic guidance.

We have then explained the potential synergy between BARR-C:2018 and MISRA C:2012. They are amenable to parallel adoption: a project seeking MISRA C compliance can use the coding style portion of BARR-C:2018 thereby satisfying that MISRA C recommendation of adopting and enforcing a consistent coding style. They are also amenable to serial adoption: when a MISRA C compliance requirement is not (yet) present, the adoption of BARR-C:2018 is a major improvement with respect to the situation where no coding standards and no static analysis are used. We have shown that complying with BARR-C:2018 entails compliance with a non-negligible subset of MISRA C:2012. While going from BARR-C:2018 compliance to MISRA C:2012 compliance still requires an effort that should not be underestimated, BARR-C:2018 compliant projects and teams trained to its use and enforcement are in very good position to tackle MISRA C:2012 compliance of that and other projects.

Acknowledgments

For the notes on the history of MISRA and MISRA C we are indebted to Andrew Banks (LDRA, current Chairman of the MISRA C Working Group) and David Ward (HORIBA MIRA, current Chairman of the MISRA Project). We are also grateful to the following BUGSENG collaborators: Abramo Bagnara, for the many discussions we had on the subject; Anna Camerini for the composition of Figure 1.

References

  • [1] Embedded Systems Safety & Security Survey, Barr Group, Germantown, MD, USA, Feb. 2018, available at http://www.barrgroup.com/.
  • [2] 2011 Embedded Engineer Survey, VDC Research, Natick, MA, USA, Aug. 2011.
  • [3] R. Bagnara, A. Bagnara, and P. M. Hill, “The MISRA C coding standard and its role in the development and analysis of safety- and security-critical embedded software,” in Static Analysis: Proceedings of the 25th International Symposium (SAS 2018), ser. Lecture Notes in Computer Science, A. Podelski, Ed., vol. 11002.   Freiburg, Germany: Springer International Publishing, 2018, pp. 5–23.
  • [4] ——, “The MISRA C coding standard: A key enabler for the development of safety- and security-critical embedded software,” in embedded world Conference 2019 — Proceedings, DESIGN&ELEKTRONIK, Ed.   Nuremberg, Germany: WEKA FACHMEDIEN, Richard-Reitzner-Allee 2, 85540 Haar, Germany, 2019, pp. 543–553.
  • [5] IEC, IEC 61508-1:2010: Functional Safety of Electrical/Electronic/Programmable Electronic Safety-Related Systems.   Geneva, Switzerland: IEC, Apr. 2010.
  • [6] ISO, ISO 26262:2011: Road Vehicles — Functional Safety.   Geneva, Switzerland: ISO, Nov. 2011.
  • [7] CENELEC, EN 50128:2011: Railway applications — Communication, signalling and processing systems - Software for railway control and protection systems.   CENELEC, Jun. 2011.
  • [8] RTCA, SC-205, DO-178C: Software Considerations in Airborne Systems and Equipment Certification.   RTCA, Dec. 2011.
  • [9] General Principles of Software Validation; Final Guidance for Industry and FDA Staff, Version 2.0 ed., U.S. Department Of Health and Human Services; Food and Drug Administration; Center for Devices and Radiological Health; Center for Biologics Evaluation and Research, Jan. 2002, available at http://www.fda.gov/MedicalDevices/DeviceRegulationandGuidance/GuidanceDocuments/ucm085281.htm.
  • [10] P. Cousot, R. Cousot, J. Feret, A. Miné, L. Mauborgne, D. Monniaux, and X. Rival, “Varieties of static analyzers: A comparison with ASTREE,” in First Joint IEEE/IFIP Symposium on Theoretical Aspects of Software Engineering (TASE 2007).   Shanghai, China: IEEE Computer Society, Jun. 2007, pp. 3–20.
  • [11] C. Jones and O. Bonsignour, The Economics of Software Quality, 1st ed.   Addison-Wesley Professional, 2011.
  • [12] R. M. dos Santos and M. A. Gerosa, “Impacts of coding practices on readability,” in Proceedings of the 26th Conference on Program Comprehension (ICPC 2018).   Gothenburg, Sweden: Association for Computing Machinery, 2018, pp. 277––285.
  • [13] MISRA, MISRA-C:2012 — Guidelines for the use of the C language critical systems.   Nuneaton, Warwickshire CV10 0TU, UK: HORIBA MIRA Limited, Feb. 2019, third edition, first revision.
  • [14] M. Barr, BARR-C:2018 — Embedded C Coding Standard.   www.barrgroup.com: Barr Group, 2018.
  • [15] ISO/IEC, ISO/IEC 9899:1999/Cor 3:2007: Programming Languages — C, Technical Corrigendum 3 ed.   Geneva, Switzerland: ISO/IEC, 2007.
  • [16] R. Bagnara, “That’s C, baby. C!” Report arXiv:1909.06353 [cs.PL], 2019, available at http://arxiv.org/.
  • [17] MISRA, MISRA C:2012 — Guidelines for the use of the C language in critical systems.   Nuneaton, Warwickshire CV10 0TU, UK: MIRA Ltd, Mar. 2013.
  • [18] The Motor Industry Research Association, Development Guidelines For Vehicle Based Software.   Nuneaton, Warwickshire CV10 0TU, UK: The Motor Industry Research Association, Nov. 1994.
  • [19] Motor Industry Software Reliability Association, MISRA-C:1998 — Guidelines for the use of the C language in vehicle based sofware.   Nuneaton, Warwickshire CV10 0TU, UK: MIRA Ltd, Jul. 1998.
  • [20] Motor Industry Software Reliability Association, MISRA-C:2004 — Guidelines for the use of the C language in critical systems.   Nuneaton, Warwickshire CV10 0TU, UK: MIRA Ltd, Oct. 2004.
  • [21] Motor Industry Software Reliability Association, MISRA C++:2008 — Guidelines for the use of the C++ language in critical systems.   Nuneaton, Warwickshire CV10 0TU, UK: MIRA Ltd, Jun. 2008.
  • [22] ISO/IEC, ISO/IEC 9899:1990: Programming Languages — C.   Geneva, Switzerland: ISO/IEC, 1990.
  • [23] ——, ISO/IEC 9899:1999: Programming Languages — C.   Geneva, Switzerland: ISO/IEC, 1999.
  • [24] ——, ISO/IEC 9899:1990/AMD 1:1995: Programming Languages — C.   Geneva, Switzerland: ISO/IEC, 1995.
  • [25] A. Banks, “MISRA C — recent developments and a road map to the future,” Presentation slides available at http://www.his-2018.co.uk/session/misra-c-updates-2016, Nov. 2016, presented at the High Integrity Software Conference 2016, Bristol, UK, November 1, 2016.
  • [26] ISO/IEC, ISO/IEC 9899:2011: Programming Languages — C.   Geneva, Switzerland: ISO/IEC, 2011.
  • [27] ——, ISO/IEC 9899:2018: Programming Languages — C.   Geneva, Switzerland: ISO/IEC, 2018.
  • [28] VV. AA., “JSF Air vehicle C++ coding standards for the system development and demonstration program,” Lockheed Martin Corporation, Document 2RDU00001, Rev C, Dec. 2005.
  • [29] ——, “JPL institutional coding standard for the C programming language,” Jet Propulsion Laboratory, California Institute of Technology, Tech. Rep. JPL DOCID D-60411, Mar. 2009.
  • [30] CERT, SEI CERT C Coding Standard: Rules for Developing Safe, Reliable, and Secure Systems, 2016th ed.   Software Engineering, Carnegie Mellon University, 2016.
  • [31] Software Engineering Center, Embedded System Development Coding Reference: C Language Edition.   Information-Technology Promotion Agency, Japan, Jul. 2014, version 2.0.
  • [32] MISRA, MISRA Compliance:2016 — Achieving compliance with MISRA Coding Guidelines.   Nuneaton, Warwickshire CV10 0TU, UK: HORIBA MIRA Ltd, Apr. 2016.
  • [33] M. Barr, Embedded C Coding Standard.   6030 Marshalee Dr, #355 Elkridge, Maryland 21075, USA: Netrino, LLC, 2009.
  • [34] ——, Embedded C Coding Standard.   Germantown, MD, USA: Barr Group, 2013.
  • [35] M. Barr and D. Smith, “Top 10 bug-killing coding standard rules,” Available at https://barrgroup.com/embedded-systems/how-to/top-ten-bug-killing-rules-webinar, Jun. 2014.
  • [36] B. W. Kernighan and P. J. Plauger, The Elements of Programming Style, 2nd ed.   New York, NY, USA: McGraw-Hill, Inc., 1978.
  • [37] C. B. Mills and L. J. Weldon, “Reading text from computer screens,” ACM Computing Surveys, vol. 19, no. 4, pp. 329–357, 1987.
  • [38] M. A. Covington, “Computer languages in type,” Journal of Scholarly Publishing, vol. 26, no. 1, pp. 34–41, 1994.
  • [39] H. Ledgard and J. Tauer, Professional Software; Vol. 2: Programming Practice.   Boston, MA, USA: Addison-Wesley Longman Publishing Co., Inc., 1987.
  • [40] B. W. Kernighan and R. Pike, The Practice of Programming.   Boston, MA, USA: Addison-Wesley Longman Publishing Co., Inc., 1999.