embedded software boot camp

Proposed Rule Changes for Embedded C Coding Standard

Wednesday, June 20th, 2018 by Michael Barr

My book Embedded C Coding Standard began as an internal coding standard of a consulting company and was first published in 2008 by that company (Netrino). In 2013, the book’s cover was given a new look and the standard became known as “Barr Group‘s Embedded C Coding Standard“. A 2018 update to the book will be released soon and this will be the first time the substance of the standard has changed in over a decade.

The primary motivation for making changes is to better harmonize the rules with the MISRA-C Guidelines. The older Barr Group standard made reference to MISRA C:2004, which was superseded by MISRA C:2012. The few known direct conflicts between BARR-C:2013 and MISRA C (stemming from our earlier embrace of ISO C99) were effectively eliminated with their 2012 update. But we wanted to do more than just remove those noted conflicts and push even further in our embrace of harmonization.

In a sentence, MISRA C is a safer subset of the C language plus a set guidelines for using what is left of the language more safely. In about as many words, BARR-C is a style guide for the C language that reduces the number of defects introduced during the coding phase by increasing readability and portability. It turns out there is quite a bit of value in combining rules from both standards. For example, MISRA’s guidelines do not provide stylistic advice and applying BARR-C’s stylistic rules to the C subset further increases safety.

The rest of this post is a preview of the specific rule changes and additions we will make in BARR-C:2013. (Omitted from this list are rules reworded simply for greater clarity.)

Rule 1.1.d (new)

The following rule will be added:

Preprocessor directive #define shall not be used to alter or rename any keyword or other aspect of the programming language.

Rule 1.6.b (new)

The following rule will be added:

Conversion from a pointer to void to a pointer to another type shall be cast.

Rule 1.7.c (change)

The earlier rule:

The goto keyword shall not be used.

will be replaced with:

It is a preferred practice to avoid all use of the goto keyword. If goto is used it shall only jump to a label declared later and in the same or an enclosing block.

This is being done so that the BARR-C standard does not restrict uses of goto that are permissible under MISRA C.

Rule 1.7.d (change)

The earlier rule:

The continue keyword shall not be used.

will be replaced with:

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

This is being done so that the BARR-C standard does not restrict uses of continue that are permissible under MISRA C.

Rule 1.7.e (eliminated)

There will no longer be any restriction on the use of the break keyword. This is being done so that the BARR-C standard does not restrict uses of break that are permissible under MISRA C.

Rule 4.2.d (change)

The earlier rule:

No header file shall contain a #include statement.

will be replaced with:

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

This is being done because apparently no one (other than me) actually valued the old rule. 🙂

Rule 5.1.c (new)

The following rule will be added:

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

Rule 5.4.b.v (new)

The following rule will be added:

Always invoke the isfinite() macro to check that prior calculations have resulted in neither infinity nor NaN.

Rule 5.6.a (new)

The following rule will be added:

Boolean variables shall be declared as type bool.

Rule 5.6.b (new)

The following rule will be added:

Non-Boolean values shall be converted to Boolean via use of relational operators (e.g., < or !=), not via casts.

Rule 6.2.c (changed)

The earlier rule:

All functions shall have just one exit point and it shall be at the bottom of the function. That is, the keyword return shall appear a maximum of once.

will be replaced with:

It is a preferred practice that all functions shall have just one exit point and it shall be via a return at the bottom of the function.

Rule 6.3.b.iv (new)

The following rule will be added:

Never include a transfer of control (e.g., return keyword).

Rule 7.1.n (new)

The following rule will be added:

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

Rule 7.1.o (new)

The following rule will be added:

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].

Rule 7.2.c (new)

The following rule will be added:

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

Rule 7.2.d (new)

The following rule will be added:

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

Rule 8.2.a (changed)

The earlier rule:

The shortest (measured in lines of code) of the if and else if clauses should be placed first.

will be replaced with:

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

Rule 8.3.c (new)

The following rule will be added:

Any case designed to fall through to the next shall be commented to clearly explain the absence of the corresponding break.

Rule 8.5.b (new)

The following rule will be added:

The C Standard Library functions abort(), exit(), and setjmp()/longjmp() shall not be used.

If you have questions about any of these draft changes or suggestions for better or other changes, please comment below.

Tags: , , , , , ,

16 Responses to “Proposed Rule Changes for Embedded C Coding Standard”

  1. Luca Matteini says:

    I like all the changes and additions but… well, as I coded over the years many (simple) multi tasking executives, the last new 8.5.b would not find my favor, somewhat. I’ve mixed feelings.

    However, time has passed and I’d say that every day fewer ones should be tempted by setjmp/longjmp more than they would by a “goto”. At the same time, people in search for task/thread/fiber management go headlessness for RTOSes that not always shine for security too.
    This remembers me nightmares of some software I had to revise in the 80s, in assembly of course, where the original developer jumped/branched all the time here and there, for “code reuse”(!)

  2. Jimmy Pedersen says:

    These all sounds nice and addresses most the minor issues (1.1.d, 1.7.c, 4.2.d, 6.2.c) I had with the standard
    Thanks for your continued work with the standards

  3. Ray Keefe says:

    Seems like a reasonable step forward. We do have one client who insisted we use setjmp()/longjmp() so that would not have been compliant.

    We have a done a lot of MISRA compliant projects and they used a rule where you could only break a rule if there was a documented reason and it was signed off. The equivalent of a quality system concession. Can be done but has to be intentional, justified and approved.

  4. Ben Sweet says:

    Re: Rule 6.3.b.iv (new)

    The following rule will be added:
    Never include a transfer of control (e.g., return keyword).

    This statement seems like it is missing something, unless I am reading it incorrectly.
    Never include a transfer of control … (in what? A macro?)

    ~Ben
    ~~~~~~~~~~~~~~~~~~

  5. Michael Simpson says:

    It all sounds reasonable. I do have a question about 4.2.d: is there a definition of a “private header file”?

  6. Bob Paddock says:

    “Rule 5.1.c (new)
    The following rule will be added:

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

    For clarity it should be explicit that the underscore is a suffix as in ‘Foo_’.

    “Rule 7.1.n (new)
    The following rule will be added:
    The names of all variables representing non-pointer handles for objects, e.g., file handles, shall begin with the letter ‘h’. ”

    and

    “Rule 7.1.o (new)
    The following rule will be added:
    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].”

    Need some examples in respect to 5.1.c. Such as ‘gppbhFoo_’ (likely intent, violates 5.1.c), ‘Foogppbh_’ (yuck, yet compliant), ‘Foo_gppbh’ (Not compliant with 7.1.o)?

    Also should it not be [h|b][g][p|pp] in respect to 7.1.n? Otherwise reorder these two rules?

    I know I lost this argument long ago, I never agree with prefixed notation. For exactly the above issues. Destroys any sense of a sorted symbol table or map etc.
    Suffixed notation avoids this and has other advantages that I’ve documented in my blog in the past.

    “Rule 5.6.a (new)
    The following rule will be added:
    Boolean variables shall be declared as type bool.”

    ‘bool_t’ should also be an allowed type to match the format of .

    “Rule 6.2.c (changed)
    The earlier rule:
    All functions shall have just one exit point and it shall be at the bottom of the function. That is, the keyword return shall appear a maximum of once.
    will be replaced with:
    It is a preferred practice that all functions shall have just one exit point and it shall be via a return at the bottom of the function.”

    “Rule 6.3.b.iv (new)
    The following rule will be added:
    Never include a transfer of control (e.g., return keyword).”

    Feels like a direct contradiction of 6.2.c.
    I understand the intent, the interaction between the these two rules needs some work in the language.

    The Barr Standard has been usable with Gimpel Lint in the past. Read VERY CAREFULLY the new license agreement with the newest versions. I’ll expound on that in my blog.

  7. Andrew says:

    I’m still not convinced by 4.2d)

    My view is that an include file should directly #include all necessary header files – this ensures that analysis (and build) is coherent, without a programmer having to guess what else is needed.

    A header file that *assumes* prior inclusion of other header files is unhelpful… such documentation is often forgotten about!

    • Daniel says:

      Additionally, some IDEs with smart completion and/or syntax highlighting will only perform properly if the type definitions are available to it (by being #included).

      I don’t think a coding standard should include rules that inhibit tools from doing static error checking.

      • Michael Barr says:

        I’m not aware of anything in the old or new language of Rule 4.2.d that could prevent a static analysis tool from being able to see the declarations of types used in source files. Ultimately, the pattern of #includes always has to support compilation.

  8. Dan Tebbs says:

    I love it! With these changes I am 100% of accord. Thanks for all your work on this!

  9. Brian Arnberg says:

    When this is finalized will you be updating your pc-lint configuration and providing that to the public?

  10. Nick says:

    Direct assignment of pointer to void to a pointer of any other type is well defined. The only reason I can think of for requiring a cast is to force us to talk about it by way of 1.6.a. Is that correct?

    If so then consider this:
    If we have a function that takes an argument of type pointer to void we have likely already documented that the function takes a pointer to void because it doesn’t care about the underlying type and operates on the data byte wise, word wise, or whatever.

    Could a better rule be “don’t use pointers to void except for making data type agnostic interfaces”?

Leave a Reply to Andrew