Code: The Good and the Ugly

Careful C craftsmanship creates correct code.

I'm just back from three weeks overseas. Despite daily trying to keep up with email, some just has to be done from the office; other items are less important and not worth dealing with from the road. So my e-mail inbox is stuffed to explosively-dangerous levels, the desk piled high with papers needed attention, and the voicemail is, well, happily minimal. E-comm has, for me at least, almost entirely replaced the phone over the last decade or so.

A couple of coding themes have popped up, though, from reading clients' code and e-mail from various correspondents.

First is an increasing trend I'm seeing where developers rely on an exquisite knowledge of precedence rules in C, usually inside of if statements. A generic example:

if( variable1 operator1 variable2 operator2 variable3)do_something;

Absent parenthesis to group elements of this expression, the result may be very surprising. The statement:

 if( variable1 & variable2 == variable3)do_something;

probably won't do what is expected. Ditto for:

 if( variable1 < variable2 < variable3)do_something;

I strongly believe in using parenthesis in any instance where there is the slightest possibility of confusion. Cost: zero. Benefit: possibly saving a lot of debugging and maintenance time.

(In fact, the code I read while traveling incorrectly combined operators and was the source of a long-lurking bug. That "exquisite knowledge precedence rules" was sorely lacking. There's a lot of complexity to the C standard, and it's a bad idea to assume one's own perfect understanding, or that of a colleague or future maintainer).Another construct that keeps surfacing looks something like:

 #define TIME  28*60               // Comment of some sort                                  // This value may not exceed 					    // 1800, for some reason

The good news is that the max limit is carefully commented. Assume thatTIME is defined in seconds; 28*60 is not a bad way to express 28 minutesin a clear way. However, this construct puts the burden of proving28*60 < 1800 on the developer; later hurried changes, say editing 28to 31 to meet some requirements change, will bust the limit. Add this:

 #if TIME > 1800                // Enforce the 1800 second limit  #error TIME exceeds 1800 seconds#endif  

Now the compiler will enforce the limit. (Some may encode the 1800 into its own #define ).

Further, TIME is a terrible name; since it has units, those units shouldbe encoded in the name so later code doesn't confuse seconds withminutes, hours, or fortnights. Better: TIME_SECONDS . (I was at an Adaconvention in Berlin on this trip; the careful use of Ada's strongtyping makes such a mistake impossible.)

Finally, frequent correspondent Bandit sent this link: http://imranontech.com/2007/01/24/using-fizzbuzz-to-find-developers-who-grok-coding/.Turns out, a scary number of developers can't construct the simplestprograms in an interview test. Frankly, at first I thought the article atroll as such incompetence seems unlikely. Readers' comments though, inmany cases prove the thesis.

Surely readers of Embedded.com are far more capable than that article suggests.

Jack G. Ganssle is a lecturer and consultant on embedded developmentissues. He conducts seminars on embedded systems and helps companieswith their embedded challenges, and works as an expert witness onembedded issues. Contact him at . His website is.

16 thoughts on “Code: The Good and the Ugly

  1. Not to mention that TIME define should have parentheses  if its more than just a value. x = TIME / 72; will yield some interesting results in its current form.

    Log in to Reply
  2. Explicit parenthesis not only enforce predictable behavior on the compiler, they also provide 'documentation' of intent when changes are needed at a later date.

    I hate inhereting code with implicit execution dependencies. Generally, as I unravel each sect

    Log in to Reply
  3. With respect to that FizzBuzz article, never have I see so many responses to a single thread on some computing topic before. It's like everybody wanted to show 'their stuff' to this simple problem. I won't comment on the quality of these solutions, but e

    Log in to Reply
  4. Get a coding standard and lint and USE THEM! I highly recommend Misra C. Although it is aimed at safety-critical use in the auto industry, it will “steer” you right and prevent a multitude of errors. Get a copy of PC-Lint to go with it and learn to love

    Log in to Reply
  5. What particular interesting results do you have in mind? The result of (28*60)/72 and 28*60/70 will always be the same. The order of evaluating the '*' and '/' operators is always from left-to-right.

    Log in to Reply
  6. Guess what would happen if:
    #define TIME DEFAULT_TIME + 10, the efect will be:
    DEFAULT_TIME + 10/72 but the programmer expected
    (DEFAULT_TIME + 10)/72

    Log in to Reply
  7. I can't stand it when I run across code from a fancy-pants programmer. 🙂

    Seriously, if you're going to maintain code over the years, with different developers touching it, make it simple to read, use lots of comments, lots of parenthesis and lots of whi

    Log in to Reply
  8. I think some clown programmers find it revolutionary and stylist to code this way.
    As far as I am concern, coding to be precise, free from syntax and logical error isn't an “old school” thing.
    We can encourage the good practices and standards, but there ar

    Log in to Reply
  9. No amount of added parenthesis will make [code] if( variable1 .lt. variable2 .lt. variable3)do_something [/code] do what is probably expected. No matter which .lt. (web page won't let me enter the actual symbol) is evaluated first, the result is eithe

    Log in to Reply
  10. Avoiding something subtle and silent that can take 100% of your debugging time for a day or two is worth it. I'd say more coding errors happen because people don't know how to touch-type, and are looking to save a few keystrokes, than anyone would care to

    Log in to Reply
  11. Multiply and divide, yes; addition, no. And even multiply and divide are different if you were working (and thinking) in Pascal on another project, where the evaluation is right to left. Tell me, do you get charged extra for parentheses by your compiler?

    Log in to Reply

Leave a Reply

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