Which coding standard is best for embedded software?

As you may recall, It's not that I can’t write C per se — it's just that I don’t write very good C (LOL). Thus, I'm currently on a quest to learn C/C++ (see What's the best C/C++ course for someone like me? ).

The problem is that I'm a hardware design engineer by trade. I dabble at programming — now mostly as part of my hobby projects — and I largely make things up as I go along. The end result is that I tend to spend an inordinate amount of time debugging my code. Sometimes the simplest thing can trip me up for ages. For example, I recently took a global int declaration that looked something like the following…

  int pinTiming = 7;

…and I converted it into a #define directive that looked something like the following…

  #define pinTiming 7;

This isn't the exact example, but it's close enough for you to get the idea. As you can see, I remembered to remove the equal symbol, but I forgot to strip out the semicolon at the end. I also made a few other tweaks throughout the body of the program. “This is wasy-peasy,” I thought to myself… until I tried to compile the little scamp and the compiler hung up. Initially, I focused on the changes I’d made to the body of the program, so it took me ages to track this little rapscallion down.

One problem I have is that I've fallen into the trap of wanting my programs to look like “big boy code.” In the past, I've seen code written by professional programmers that has been concise and sparing in its use of white space characters, and that has given the impression that its creator knew “what was what.” On the other hand, this code has also often been cryptic and hard to read.

If you work for a large company, they will probably dictate the coding style you use. If you work for a smaller company, it may be more of a “free for all.” And if you are an individual, you're pretty much on your own.

There are a lot of books on programming, but they typically focus on teaching the use of the various language operators and constructs. When it comes to coding “style,” different books tend to reflect the personal preferences of the author. Take the following two versions of the same snippet of code, for example:

  // Version A  for(i=1;i<10;i++){    // Statements go here  }  // Version B  for (i = 1; i < 10; i++)  {      // Statements go here  }

Should there be a space after the for (Version B) or no space (Version A)? Should we use white space to separate things out between the standard parentheses (Version B) or no white space (Version A)? Should the opening squiggly bracket appear on a new line (Version B) or on the same line as the for (Version A)? Should we indent the statements forming the body code using four spaces (Version B), two spaces (Version A), or some other number of spaces?

Where do you go to learn this sort of thing? Well, I know where I go, because I just read the Embedded C Coding Standard by Michael Barr of the Barr Group. At only 88 pages, this isn’t a large tome, but as far as I'm concerned it's worth its weight in gold. The really good news is that it's only $9 for a PDF download and the same for a hard copy (print version) shipped by standard mail in the USA (it's $19 for a hard copy shipped anywhere else in the world).


(Source: BarrGroup.com)

The overriding reason Mike and his colleagues created this standard is to reduce the number of bugs in embedded software (a.k.a. firmware), including code added or modified later by maintainers.

I was chatting with Mike on the phone just a few minutes ago as I pen these words. He acknowledged that a lot of code writing comes down to personal preference, so -- when it came to creating this standard -- he and his co-contributors sat around the table arguing each point. The only criterion for selecting one style rule over another was that rule's ability to minimize potential bugs.

The book is divided into major sections, like Comments, White Space, Data Types, Variables, and so forth. Each of these sections is then sub-divided into a number of topics. In the case of White Space, for example, we have sub-topics of Spaces, Alignment, Blank Lines, Indentation, Tabs, and Linefeeds.

As an aside, the term Whitespace (paradoxically containing no spaces) is an esoteric programming language developed by Edwin Brady and Chris Morris at the University of Durham Its name is a reference to white space characters.

As it says on the Whitespace page on Wikipedia: Unlike most programming languages, which ignore or assign little meaning to most white space characters, the Whitespace interpreter ignores any non-whitespace characters. Only spaces, tabs and linefeeds have meaning. An interesting consequence of this property is that a Whitespace program can easily be contained within the whitespace characters of a program written in another language...

But we digress... each of the sub-sections starts off with its associated rules. These rules are followed by the reasoning behind them, any permissible exceptions, and the ways in which the rules are to be enforced.

Let's take the use of braces (squiggly brackets), for example. Over the years, I've bounced back and forth between having the left brace ('{') appear on the same line as its if , else , for etc. statement, or having it appear by itself on the line below the start of the block it opens. Here's what the Embedded C Coding Standard has to say:

Braces:
Rules:

  1. Braces shall always surround the blocks of code (a.k.a. compound statements) following if, else, switch, while, do, and for statements; single statements and empty statements following these keywords shall also always be surrounded by braces.
  2. Each left brace ('{') shall appear by itself on the line below the start of the block it opens, The corresponding right brace ('}') shall appear by itself in the same position the appropriate number of lines later in the file.

Reasoning: There is considerable risk associated with the presence of empty statements and single statements that are not surrounded by braces. Code constructs like this are often associated with bugs when nearby code is changed or commented out. This risk is entirely eliminated by the consistent use of braces. The placement of the left brace on the following line allows for easy visual checking for the corresponding right brace.

What can I say, except that I totally agree with all of these points? I've tried having the left brace on the same line as my if and for statements because I thought it made my code look "professional." As a result, I've spent an inordinate amount of time trying to determine which left brace was associated with which right brace.

I've also tried omitting braces when I had only a single statement. Once again, I did this because I thought using these braces would make professional programmers think I was a weed and a wet who didn’t have a clue. This is all the more pathetic when we come to realize that no one but myself ever looks at my code anyway. But having read this standard, I feel empowered to use braces for everything: multiple statements, single statements, and even empty statements.

In the case of indentation, the first rule says "Each indentation Level within a module should consist of 4 spaces" (there are additional rules that modify this first rule as necessary). The reasoning behind this reads as follows: "Fewer indentation spaces increase the risk of visual confusion, while more spaces increases the likelihood of line wraps."

Once again, I'm forced to agree with this. I've been using two spaces for indentation because this is what I've seen others use, but I just tried using four spaces on a block of my existing code and the result is much more readable.

One rule that almost made me squeal with delight was in regard to equivalence tests. This rule reads as follows: "When evaluating the equality or inequality of a variable with a constant value, always place the constant value on the left side of the comparison operator." What they are saying here is to use if (MAX_LOOP == loop_count) instead of using if (loop_count == MAX_LOOP) . The reason for doing this is that, in the case of the former, the compiler will flag an error if we mistakenly use a single assignment "=" instead of a dual equivalency "==". I cannot tell you how many hours my implementing this rule would have saved me in the past.

I tell you -- I read the Embedded C Coding Standard in only one evening, but it's going to dramatically change the way I write my programs in the future. So, now all I need to do is to learn C itself (LOL). Watch this space for future developments...

29 thoughts on “Which coding standard is best for embedded software?

  1. “The Barr Group book is great!nnThe only bit I don't follow is the constant on the left advice. My brain momentarily halts when it reads if(0 == x), it just seems wrong. So instead I rely on my lint and compiler to catch these errors when I inevitably ma

    Log in to Reply
  2. “Unfortunately, I'm just a hobbyist when it comes to programming, so I don;t have access to a Lint application (sad face) — on that basis, doing the comparison as (constant == variable) seems like a real good idea, even if it does take a bit of getting us

    Log in to Reply
  3. “Splint is free (FLOSS) but being a hobbyist it might be too steep a learning curve for you.nnAlso the other message is from a C compiler, most will warn about this if you set the warning level high enough. Although again setting the warning level higher

    Log in to Reply
  4. “I used “if (constant == variable)” for years, until I finally admitted to our team that the lack of readability was worse than the problem it cured. As Paul says, your compiler will alert you to assignment inside relational expressions.”

    Log in to Reply
  5. “I really think that obsession with coding standards is small mindedness.nnWhat is surely more important is try fit in with the coding standards that the project has and use those.nnClear and good code is not a result of pedantic coding standards.nnC

    Log in to Reply
  6. “Hi Steve — I agree totally that there's a lot more to writing good code than following a coding standard — but following a standard certainly cannot hurt things.nnAfter reading Mike Barr's book, I realize that there are a lot of points that — had I f

    Log in to Reply
  7. “I agree that if a project already has an existing coding style, then use that. However, my impression is that there are more than a few small companies out there that have not adopted a style, and each programmer does his/her own thing, which had to make

    Log in to Reply
  8. “Actually, your Arduino compiler should've caught it: it's a recent version of GCC under the hood, and the warning should be enabled.nnYou want to reduce bugs in code? Enable all the warnings your compiler can issue, and have it treat them like errors. T

    Log in to Reply
  9. “No, using “(constant == variable)” is /not/ a good idea. And being a hobbyist, or using hobby-style tools, is not an excuse. If your compiler doesn't support even the most basic of static warnings and error checking, get a better compiler. The comp

    Log in to Reply
  10. “Yes using “(constant == variable” IS a good idea. Everyone here is arguing that it makes code less readable and that you should use better tools (lint, newer compiler or better options with your current compiler). To address the first point, if someone

    Log in to Reply
  11. “It makes more sense to read “if (x == 1)” than “if (1 == x)”, because “x” is the thing that might have been changed to equal 1. That is how language works.nnThe majority of compilers will be able to spot likely errors such as “if (x = 1)”. In

    Log in to Reply
  12. “Well — I just ran the following and got no warnings:nnvoid setup ()n{n int valTest = digitalRead(12);n n if (valTest = 0)n {n valTest = 1;n }n}nnvoid loop()n{n}nnnI then went to “File – Preferences” and discovered

    Log in to Reply
  13. “FYI — if I make the test “if (0 = valTest)”, even with “Compiler Warnings” set to “None” — I still receive the non-cryptic message:nn”lvalue required as left operand of assignment””

    Log in to Reply
  14. “Hmmm, I don't remember checking or changing this setting on my Arduino setup. I'll have to go and change it to “All” to be sure that it finds everything.nnWhen I was writing code, we ran lint and also had our compiler set to give us all warnings. Our

    Log in to Reply
  15. “I suspect there is some confusion about warnings vs. errors.nnCompilers will always issue error messages because these prevent the compiler from completing compilation.nn”lvalue required as left operand of assignment” is an error message because the

    Log in to Reply
  16. “Formatting code in a certain way to be able to identify which bracket goes with which statement belies that this is the 21st century and we have text editors that do syntax highlighting and show associations between statements and the brackets that go wit

    Log in to Reply
  17. “”…this is the 21st century and we have text editors that do syntax highlighting and show associations between statements and the brackets that go with them.”nnIt sounds so easy when you say it quickly LOL My Arduino IDE has these capabilities — i

    Log in to Reply
  18. “Okay, I believe that some people are missing a subtle distinction between compiler errors and compiler/(other tool) warnings.na CORRECT C compiler can NEVER generate an ERROR for:nnif (x = 0) nnbecause it is CORRECT C syntax. Though it is highly dou

    Log in to Reply
  19. “I agree — at first I was confusing Errors (which are always reported) with Warnings (that can be filtered).nnI think “if (x = 0)” should always at least generate a warning — although it's syntactically OK, it's doubtful (as you say) that anyone woul

    Log in to Reply
  20. “The challenge with saying that a particular type of code should always generate a warning is that it is extremely difficult to draw lines that a compiler can follow. What about code like “while (c = getch()) …” ? Every coding standard for embedded p

    Log in to Reply
  21. “I accept everything everyone says (I'm married, I've learned my place, it's hard to out-humble me LOL) … but, “still and all” (as the Irish would say) … I can't tell you how many hours I've spent trying to track down problems of the “if (x = 0)” v

    Log in to Reply
  22. “I know that I am a little late to this party and that brace placement is infinitely controversial; but, I recently began to program in C and I obsessed about this issue. My first inclination was to place the top brace on a separate line – because, you kn

    Log in to Reply
  23. “Arrgggh — I hate that you make a good point — like you, I've agonized over this — but I've personally come to the conclusion that the braces are best on separate lines and that it's best to use 4-space indents.nnAnd since I just rewrote the code for

    Log in to Reply
  24. “That's also a good point — it's possible to get over-enthusiastic about nesting things (and don't get me started on recursion, recursion, recursion…)”

    Log in to Reply
  25. “I don't think putting the first brace on a separate line makes the code more readable. My point was it makes it less readable by spreading it out. And for the same reason taking nested logic and putting it into a hierarchy of function calls 4 levels deep

    Log in to Reply
  26. “Discussions about white space in code have been going on since before I was born, you would think that it would have been solved by now… No wait it has, clang-format solved it. nMore interesting questions are n1. why are we still #defining numbers whe

    Log in to Reply
  27. “Barr's book and standard are great. It changed how I write my code completely. I also incorporated it's use in our small company, which I believe is a good thing.nnI agree with reasoning on almost every rule and a little surprised that someone can't be

    Log in to Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.