Follow @jack_ganssle

Code - The Good and the Ugly

Summary: 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 email 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 email 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 a 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 that TIME is defined in seconds; 28*60 is not a bad way to express 28 minutes in a clear way. However, this construct puts the burden of proving 28*60 < 1800 on the developer; later hurried changes, say editing 28 to 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 should be encoded in the name so later code doesn't confuse seconds with minutes, hours or fortnights. Better: TIME_SECONDS. (I was at an Ada convention in Berlin on this trip; the careful use of Ada's strong typing makes such a mistake impossible).

Finally, frequent correspondent Bandit sent this link: . Turns out, a scary number of developers can't construct the simplest programs in an interview test. Frankly, at first I thought the article a troll as such incompetence seems unlikely. Readers' comments though, in many cases prove the thesis.

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

Published June 17, 2013