You are on page 1of 23

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 1 of 23

Home

Home
Bloggers
Posts by Category
Newsletter Signup
About Us
Contact Us

Log in

Search for:

Search Blog

How to Enforce Coding Standards Using PC-Lint


Firmware Forensics: Best Practices in Embedded Software Source Code Discovery

Dont Follow These 5 Dangerous Coding Standard Rules


Tuesday, August 30th, 2011 by Michael Barr
Over the summer I happened across a brief blog post by another firmware developer in which he presented ten C coding rules
for better embedded C code. I had an immediate strong negative reaction to half of his rules and later came to dislike a few
more, so Im going to describe what I dont like about each. Ill refer to this author as BadAdvice. I hope that if you have
followed rules like the five below my comments will persuade you to move away from those toward a set of embedded C
coding rules that keep bugs out. If you disagree, please start a constructive discussion in the comments.
Bad Rule #1: Do not divide; use right shift.
As worded, the above rule is way too broad. Its not possible to always avoid Cs division operator. First of all, right shifting
only works as a substitute for division when it is integer division and the denominator is a power of two (e.g., right shift by
one bit to divide by 2, two bits to divide by 4, etc.). But Ill give BadAdvice the benefit of the doubt and assume that he meant
to say you should use right shift as a substitute for division whenever possible.
For his example, BadAdvice shows code to compute an average over 16 integer data samples, which are accumulated into a
variable sum, during the first 16 iterations of a loop. On the 17th iteration, the average is computed by right shifting sum by 4
bits (i.e., dividing by 16). Perhaps the worst thing about this example code is how much it is tied a pair of #defines for the
magic numbers 16 and 4. A simple but likely refactoring to average over 15 instead of 16 samples would break the entire
exampleyoud have to change from the right shift to a divide proper. Its also easy to imagine someone changing AVG_COUNT
from 16 to 15 without realizing about the shift; and if you didnt change this, youd get a bug in that the sum of 15 samples
would still be right shifted by 4 bits.
Better Rule: Shift bits when you mean to shift bits and divide when you mean to divide.
There are many sources of bugs in software programs. The original programmer creates some bugs. Other bugs result from
misunderstandings by those who later maintain, extend, port, and/or reuse the code. Thus coding rules should emphasize
readability and portability most highly. The choice to deviate from a good coding rule in favor of efficiency should be taken
only within a subset of the code. Unless there is a very specific function or construct that needs to be hand optimized,
efficiency concerns should be left to the compiler.
Bad Rule #2: Use variable types in relation to the maximum value that variable may take.
BadAdvice gives the example of a variable named seconds, which holds integer values from 0 to 59. And he shows choosing
char for the type over int. His stated goal is to reduce memory use.

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 2 of 23

In principle, I agree with the underlying practices of not always declaring variables int and choosing the type (and
signedness) based on the maximum range of values. However, I think it essential that any practice like this be matched with a
corresponding practice of always declaring specifically sized variables using C99s portable fixed-width integer types.
It is impossible to understand the reasoning of the original programmer from unsigned char seconds;. Did he choose char
because it is big enough or for some other reason? (Remember too that a plain char may be naturally signed or unsigned,
depending on the compiler. Perhaps the original programmer even knows his compilers chars are default unsigned and
omits that keyword.) The intent behind variables declared short and long is at least as difficult to decipher. A short integer
may be 16-bits or 32-bits (or something else), depending on the compiler; a width the original programmer may have (or may
not have) relied upon.
Better Rule: Whenever the width of an integer matters, use C99s portable fixed-width integer types.
A variable declared uint16_t leaves no doubt about the original intent as it is very clearly meant to be a container for an
unsigned integer value no wider than 16-bits. This type selection adds new and useful information to the source code and
makes programs both more readable and more portable. Now that C99 has standardized the names of fixed-width integer
types, declarations involving short and long should no longer be used. Even char should only be used for actual character
(i.e., ASCII) data. (Of course, there may still be int variables around, where size does not matter, such as in loop counters.)
Bad Rule #3: Avoid >= and use <.
As worded above, I cant say I understand this rule or its goal sufficiently, but to illustrate it BadAdvice gives the specific
example of an if-else if wherein he recommends if (speed < 100) ... else if (speed > 99) instead of if (speed <
100) ... else if (speed >= 100). Say what? First of all, why not just use else for that specific scenario, as speed must
be either below 100 or 100 or above.
Even if we assume we need to test for less than 100 first and then for greater than or equal to 100 second, why would anyone
in their right mind prefer to use greater than 99? That would be confusing to any reader of the code. To me it reads like a bug
and I need to keep going back over it to find the logical problem with the apparently mismatched range checks. Additionally, I
believe that BadAdvices terse rationale that Benefits: Lesser Code is simply untrue. Any half decent compiler should be
able to optimize either comparison as needed for the underlying processor.
Better Rule: Use whatever comparison operator is easiest to read in a given situation.
One of the very best things any embedded programmer can do is to make their code as readable as possible to as broad an
audience as possible. That way another programmer who needs to modify your code, a peer doing code review to help you
find bugs, or even you years later, will find the code hard to misinterpret.
Bad Rule #4: Avoid variable initialization while defining.
BadAdvice says that following the above rule will make initialization faster. He gives the example of unsigned char
MyVariable = 100; (not preferred) vs:
#define INITIAL_VALUE 100
unsigned char MyVariable;
// Before entering forever loop in main
MyVariable = INITIAL_VALUE

Though its unclear from the above, lets assume that MyVariable is a local stack variable. (It could also be global, the way
his pseudo code is written.) I dont think there should be a (portably) noticeable efficiency gain from switching to the latter.
And I do think that following this rule creates an opening to forget to do the initialization or to unintentionally place the
initialization code within a conditional clause.
Better Rule: Initialize every variable as soon as you know the initial value.
Id much rather see every variable initialized on creation with perhaps the creation of the variable postponed as long as
possible. If youre using a C99 or C++ compiler, you can declare a variable anywhere within the body of a function.
Bad Rule #5: Use #defines for constant numbers.
The example given for this rule is of defining three constant values, including #define ON 1 and #define OFF 0. The
rationale is Increased convenience of changing values in a single place for the whole file. Provides structure to the code.

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 3 of 23

And I agree that using named constants instead of magic numbers elsewhere in the code is a valuable practice. However, I
think there is an even better way to go about this.
Better Rule: Declare constants using const or enum.
Cs const keyword can be used to declare a variable of any type as unable to be changed at run-time. This is a preferable way
of declaring constants, as they are in this way given a type that can be used to make comparisons properly and enabling them
to be type-checked by the compiler if they are passed as parameters to function calls. Enumeration sets may be used instead
for integer constants that come in groups, such as enum { OFF = 0, ON };.
Final Thoughts
There are two scary things about these and a few of the other rules on BadAdvices blog. First, is that they are out there on the
Internet to be found with a search for embedded C coding rules. Second, is that BadAdvices bio says he works on medical
device design. Im not sure which is worse. But I do hope the above reasoning and proposed better rules gets you thinking
about how to develop more reliable embedded software with fewer bugs.
Tags: bugs, embedded, firmware, programming, safety, standards
This entry was posted on Tuesday, August 30th, 2011 at 2:13 pm and is filed under Coding Standards, Efficient C/C++, Firmware Bugs. You can follow
any responses to this entry through the RSS 2.0 feed. You can skip to the end and leave a response. Pinging is currently not allowed.

57 Responses to Dont Follow These 5 Dangerous Coding Standard Rules


1. Krzysztof Wesoowski says:
August 30, 2011 at 4:03 pm
Hello,
Very nice post, dealing with many bad ideas or optimization myths. I would add some points:
@Bad Rule 1:
It is really easy for compiler writers to detect such power of two divisions and replace them with shift, so many
compilers will generate exactly same object code even with O1.
@Bad Rule 2:
I would personally add: If stdint.h is not available use #ifdefs to typedef standard types to C99s portable fixed-width
integer types. It is more convenient not to interface with code using millions variations of fixed-width integers (like u8,
uint8, etc).
Also using fast types may be vary useful when declaring local variables.
@Bad Rule 5:
Using #defines has one advantage if place of #define is far away from place of use (for example #defines based
configuration) you can use #ifdef and #error directive to check some assertions for example that some buffer has size
being power of two etc.
Reply
Eric Wertz says:
August 31, 2011 at 7:58 pm
I agree with you about your specified virtue of using the preprocessor to help mitigate some of the liabilities of
simply using a #define. Id like to add two more.
First, #defines dont consume (precious, if youre on such a platform) SRAM where as const constructions
generally do. If one is documenting a ton of symbols, in particular in a header file for general use, then the
probability exists that the majority of the defined symbols will be unused, and will consume SRAM. If the tool
chain is smart enough (or if youre willing to pay a premium for one that does), it could eliminate the unused
constants, but many/most dont. Enums dont have this liability, as theyre merely type definitions and not
variable(-like) declarations.
Second, the problem with allocating space for consts is that it (in practice) precludes the compiler from encoding
the constant as an immediate in the operand for the instruction if its small enough, which also benefits code space

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 4 of 23

as well as performance. Most compilers _are_ smart enough to do constant folding so that even if the constant has
to go into SRAM, only one instance will be created (albeit perhaps only in module-scope) depending on the
toolchain.
For uses of consts as constant symbols in module scope that are declared and not used, the first reservation is a
non-issue and isnt the worst practice. In my opinion, enums are fine solution iff you fully intent to make full use
of the type definition that comes out of it, and dont simply use it as a symbolic constant that gets slopped-around
between variables of other types (chars, uintN_t, etc.).
I havent checked but my memory of enums was that theyre int-sized, which has all of the space-penalty
liabilities for those of us that work on resource-constrained systems, if my target requires only 8/16 bits.

About your reservations regarding BadRule2, why not just use typedefs rather than #defines to establish the C99
types? By not using typedefs you dont get any of the strong-typing benefits that Michael rightly wants to
perpetuate, whereas #defining them merely maps them to their weakly-specified types (int, long, etc.) without
almost none of the benefits.

The other comment is that most compilers are also smart enough to be able to identify the many of the worst
#defined constructions at their point of (mis-)use in particular, constants known to be assigned inappropriate
lvalues (signed where unsigned is required, or stores into datatypes are too small for the #defined rvalue). Maybe
not in all cases, but in many. Id love to know about common counter-examples, although only reasonable, nontoy compilers need apply

As far as BadRule1 and BadRule3 are concerned, I cant help but say The 1980s called and they want their
compilers back. Unless one can definitively otherwise, the compiler *is* smarter than you are. These two
rules are clearly dead-fish waving.
Reply
2. Carle Henson says:
August 30, 2011 at 4:20 pm
I think whoever wrote rule 1 must be living in the far distant past when compilers were not intelligent in terms of
optimization and we had to wring every last cycle out of the code. Perhaps there are still severely limited processors
with outdated compilers but all of the compilers I have used in many years would do the shift optimization for you if it
can.
Reply
hpro says:
September 15, 2011 at 12:43 pm
It actually gets better. The compiler will do *better* division than you can do manually.
Check out http://ridiculousfish.com/blog/archives/2010/02/15/labor-of-division-episode-i/index.html for a good
example.
Modern compilers are so good, that in quite a lot of cases you will cause the compiler to generate *worse* code
because it is bending over backwards to jump through your optimization hoops.
Reply
3. Eric Smith says:
August 30, 2011 at 4:30 pm
I think an even better rule than always using the C standards fixed-width integer types is to use the standards minimum
-width integer types where the memory usage isnt critical. In other words, for a value from 0 to 10000 that is going to
be in a data structure that has a lot of instances, Id use uint16_t, but where the size is less important, Id use
uint_least16_t. This gives the compiler the flexibility to use a wider integer if it wants to, possibly for optimization. For

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 5 of 23

example, on some 32-bit processors, using uint16_t might force the compiler to add masking instructions, while it might
be more efficient to use 32-bit storage with no masking, and uint_least16_t allows that.
For code where maximum performance is essential, perhaps in an inner loop, Id go one step further and use
uint_fast16_t, which tells the compiler both that the width must be at least 16, and that I want whatever type will make
the code fastest.
Reply
Thomas Thorsen says:
August 31, 2011 at 2:44 pm
Actually you should use uint_fastXX_t to avoid masking instructions. For example, on a 32bit ARM processor,
uint_least16_t will be a 16bit type and subject to masking instructions following arithmetic operations on the
register that contains the value.
I think it is fair to say that the uint_leastXX_t types are quite useless on any platform that provides the full set of
uintXX_t types, as they are required by the standard to be identical types in this situation. Note that the uintXX_t
types are not mandatory in C99, but i doubt anyone would consider not providing them!
Reply
David Brown says:
August 31, 2011 at 4:18 pm
There are some processors (particularly DSPs) that cant access 8-bit, or perhaps even 16-bit data. On such
targets, a char is 16-bit or 32-bit, which is still valid for C. Then there is no uint8_t and perhaps no
uint16_t either but uint_least8_t is still there. So if you want to write code that will work on such a DSP
and will use the smallest type possible for better code on other cpus, you use uint_least8_t, etc.
Reply
4. Hans Van Ingelgom says:
August 30, 2011 at 4:44 pm
Another bad idea in my opinion is using enums for bit fields, like typedef enum { blinking=1, bold = 2, inverted = 4 }
fonttype; If you define an enumerated type, you are saying there is a type of which the values can be enumerated (duh!).
If you then say fonttype t = bold | blinking, the value of t is not a member of fonttype. Ive seen quite a lot of these
constructs, however I always think its wrong. Or is it just me? Also if I remember correctly, C++ makes a much bigger
fuzz about this.
Reply
Krzysztof Wesoowski says:
August 30, 2011 at 5:07 pm
C++ allows more elegant approach see http://doc.qt.nokia.com/latest/qflags.html.
Reply
scott says:
August 30, 2011 at 6:03 pm
i actually dont have a problem with this, at least if there is sufficient documentation near the definition of
fonttype that indicates that the enum is a bit field. although when i read the assigment fonttype t = bold | blinking;
i cant help but to think that t is bold *or* blinking instead of bold *and* blinking.
kinda wish there was a key word that enforced it like the [Flags] attribute in c#.
Reply
Eric Wertz says:
August 31, 2011 at 8:17 pm
I cant condone this. If you believe at all in what the abstraction of what an enum is supposed to be, using
an enum in a context where bitwise operations are desired, is an abomination. In the purest sense, one
shouldnt even know what the _range_ of values are in the enumeration. However, we all know that being
able to assign them concrete values has so much value in the real world that the language has conceded to
break the most-pure abstraction of what an enumeration is.

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 6 of 23

Bitwise operations are intended for uints, or bitfields if you really the syntactic sugar in your coding diet.
If you dont trust yourself to use | and & correctly, then you should be sticking to bitfields and stick
with the logical operators. This just isnt the right time or place for an enumerated type. If youre really
committed to writing bug-free code, one needs to recognize constructions that both the reader (and writer!)
of the code get hung up on, and steer clear of them.
Reply
Ashleigh says:
August 30, 2011 at 6:33 pm
Agreed enums should not be used for bitfields. Although you can have enums where the enumerants have any
value you care to assign (just a named number) I find it more helpful to think of then as a whole new type which
is not compatible with addition or logical operators.
So things like bitfields need to use either a struct with bit field parts in, or #defines.
Bad rule #5 should be considered alonside the compiler. If the compiler generates bigger code or larger constant
sections when declaring const then there may be good reason to use #define. In general though, the advice to
use const is better the compiler does more work.
Reply
5. Alex Converse says:
August 30, 2011 at 5:01 pm
As far as rule 5 goes, Ive been bitten by using const int instead of a define.
#define SLOTS 10
int my_array[SLOTS]; /* Standard C array */
const int slots = 10;
int my_array[slots]; /* Technically this is a Variable Length Array */
Reply
Gauthier says:
August 31, 2011 at 1:14 am
+1, and the following cannot be done with const:
#define TICK_FREQUENCY (50U)
#define SECONDS_IN_PERIOD (60U)
#define TICKS_IN_PERIOD (TICK_FREQUENCY * SECONDS_IN_PERIOD)
Furthermore if the const/define value is to be used in several modules, where is the const supposed to be defined?
In my opinion it must be in the c file, and declared as extern in the h file. This forces you to touch the c file if the
variable needs changing. Const takes also memory (although little), which define does not.
On the other hand, const are easier to debug.
Reply
6. David says:
August 30, 2011 at 5:22 pm
how to develop more reliable embedded software with fewer bugs.?
Allow peers to review it: http://youtu.be/nFZGpES-St8?t=5m
Reply
7. Ark says:
August 30, 2011 at 5:49 pm

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 7 of 23

Re Bad Rule #5:


It is not bad by itself (floats cant be enums); it looks like a restatement a MISRA rule deprecating magic numbers
The point is that symbolic names should be used.
Cs const objects cannot be eliminated from storage so they are not the same as parameter-like macros.
A case for #define in favor of enum is brought to you by sizeof and, correspondingly, offsetof. size of an enumerated
type is a cross-platform mess.
Reply
8. Ark says:
August 30, 2011 at 5:58 pm
Re Bad Rule #4
Sensibly used, it is IMO a great rule. Consider a not assigned before use bug: I just forgot to assign a value in one of
the conditional paths. Static analysis tools (e.g. Lint) will spot this rather reliably. However, early initialization to a
bogus safe value defeats this detection at build time.
Reply
Venkata Viraraghavan says:
August 31, 2011 at 1:45 am
I think this rule is to do with globals. In fact, Id say Initialize global variables to known INvalid values. That
way, the issues with soft reset will show up in the first run of the code rather than in the second. If initialized to
valid values at definition and not in an init function, they would hold previous (undefined) values during a soft
reset. This could eat up debugging time after the first run has deemed that functionality is alright.
Reply
Tom the Toolman says:
December 20, 2011 at 9:54 am
Unnecessary initialization costs code space. On some platforms, this is critical, so we have to byte the bullet
and just be careful.
Reply
9. Eduardo says:
August 30, 2011 at 6:57 pm
In the beginning of my education and then the first years of my professional career I used to believe many of these rules
and their arguments as golden rules. Mostly because I was taught that way. Many of my college professors felt pretty
important when they gave us examples that proved these rules (like the = rule) by compiling both examples and showing
us the results, having predicted them before compile time (as a student, one thinks compilers are magical). My point is
that these professors grew up (professionally) programming in assembly, and we have to remember that the first
compilers werent as good as the ones we have today, its easy to understand why many people think some of these rules
are important.
I still defend the importance of knowing the processor architecture, but its also important for code to be readable. This
is something I learned later on, when working with more people, when my code was peer-reviewed or was worked on
by other people, readability is king! Optimize where you really need to optimize, elsewhere, make the code easy to read.
Reply
10. Jeremy says:
August 30, 2011 at 7:23 pm
Enums for bitfields are more platform and compiler independent though if youre looking at port pins on a processor.
The only reason to use an enum is one of many methods to name a port IO to a particular variable.
Its not my method of choice, I would much rather have a constant structure array containing a port pointer and the port
I/O pin, and then use the enums to index into that array, but thats just me.
What I hate seeing though is people using enums to specify bits in I/O registers. There are just so many ways this can
shoot yourself in the foot, such as changing compilers, changing from 8-bit to 16-bit or 32-bit processors, etc. It can be
even worse if youre changing processor manufacturers!

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 8 of 23

Reply
11. Trenton says:
August 30, 2011 at 9:30 pm
Never shift when you mean to divide. If you really are convinced that you are better at optimizing than your compiler
use a macro like divide_x_by_32(x) and hide your shifting inside there. Also, shifting doesnt work for products or
quotients if the number being shifted is negative. Not all CPUs have single cycle shifts, some have single cycle divides,
etc. So using a macro makes it easier to port.
One reason to choose not to initialize variable when declared is to alter the time when initialization takes place.
Initialized variables are usually initialized at reset, before main(). Uninitialized variables assigned later in the code are
usually initialized when the core executes. This amortizes the time to initialize variables.
Using const variables instead of #defines occupies storage, which may or may not be what you want. You need to be
careful when using enums since many compiler treat then as signed integers, which may not be what you wanted. For
example, passing narro enums as wide arguments may cause the compiler to add code to sign extend them.
Reply
david collier says:
August 31, 2011 at 6:31 am
um, doesnt a #define specify a sequence of characters. so compilers dont treat them as signed anything, they put
the characters in the matching place, and they get treated as if they belong there. Shouldnt you be able to get the
desired effect by specifying the literal value fully?
Reply
Trenton says:
August 31, 2011 at 7:40 am
First, what I wrote about variable initialization is incorrect with respect to automatic variables in a function
invocation.
Second, what I meant about signed numbers in shifts is that -4 >> 1 doesnt equal -2.
If you use a #define to create a constant, say @define myvar -5, and then you pass that as a parameter to a
function, say f(uint32_t x) in a call like f(myvar) then the preprocessor replaces f(myvar) by f(-5) before the
compiler sees it. In this case you may get what you wanted.
If you make an enum { one = 1, two, three} then usually that will be treated as a signed value of some fixed
size (perhaps int) or a signed value of the smallest size big enough to represent the value; how this is done is
compiler dependent and may or may not be under programmer control. Assuming that the enum becomes an
int, if you then call f(long x) as f(one) then the compiler will convert the enum-as-int to a long. The point
was that passing enumerated values as parameters may cause the compiler to inject code to massage them
on the way into the function.
Reply
david collier says:
September 2, 2011 at 6:48 am
as discessed elsewhere on thsi page
Second, what I meant about signed numbers in shifts is that -4 >> 1 doesnt equal -2.
is incorrect. It may, or it may not, its implementation dependent.
Reply
12. Bill Davy says:
August 31, 2011 at 2:11 am
Rule 3 may also have the undesirable tendency to introduce another constant (99 in your example) requirng either an
expression using a constant (MaximumValue 1) ora new cosnat to be (defined ?) MaximumLessOne.

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 9 of 23

Rule 4. One reason for using #define is when a compiler cannot use conts variables to work out an array size. best to
avoid such puerile compilers but sometimes one has to. Also, for a bit field widths, a literal seems to be required. But far
better as a rule, have no literal constants in your code use const (best) or #define (if required).
Reply
13. Tomasz says:
August 31, 2011 at 2:15 am
@Bad Rule #5
IMHO declaring a constant as #define has its advantages in many cases, e.g. when one cant afford to waste too much
RAM. One other reason in small and slow environments, i.e. 8 bit uCs, it makes sense to load an immediate value into
a variable, since its faster than loading one const to a register and only then copying it to another variable. There are
times when I have to do such optimization due to sb-elses poor hardware design (e.g. a system that was meant to do
sth very simple now has to do more complex tasks on the same machine), although I agree it needs extra care from my
side. This is a particular situation, because I always know that the code is not going to be maintained by anybody else.
Reply
David Brown says:
August 31, 2011 at 2:28 pm
If you declare something as const int two = 2; at file scope, it has external linkage. That means the compiler has
to assume that anyone can change its value (yes, const variables are variables not true constants) from other
modules that the compiler cannot see at compile time. So the constant two gets allocated space in ram (or
sometimes flash), and this space must be read when you use it. And x = x / two; means using a division
instruction or library call.
The correct way to define such constants is static const two = 2; then the compiler knows exactly when and
how two is used, and can see that it is never changed. It can then substitute the literal value 2 for two
throughout the code, and x = x / two; becomes a right-shift operation.
Reply
14. Konrad says:
August 31, 2011 at 2:59 am
Re Bad Rule 1:
The important thing to remember about using right shifts for division is that it rounds the quotient of a signed dividend
towards minus infinity. -1 >> 1 is -1, not 0.
I suspect (as the original code is not shown) that the problem of mismatched loop size and shift width is easily remedied
by preventing the code from compiling when these values do not match. In this case, rather than testing for !
(loop_counter % 16), it would be better to define log2_size as 4, use !(1 <> log2_size when calculating the average.
The critique that the resulting code can only be used for power-of-two sample sizes (and not for a sample size of say,
15) is offset by the fact that the code runs much quicker for these sizes, as both the division and the detection of that the
loop counter is 0 modulo 16 (or whatever). Hence, run-time is quite non-linear in the choice of sample size, and if the
underlying problem is robust in the sample size (quite likely, since we are calculating averages), it makes sense to
program run-time performance rather than for unnecessary generality.
In fact, coding in this way prevents subsequent maintainers from lightheartedly changing the value such that this
particular section of code runs drastically slower.
In general, integer arithmetic has many interesting properties that one can exploit; compilers cannot do this in general.
More importantly, it has limitations (such as overflow) which prevent it from being applied blindly. Mastering this
requires practice. A piece of code using shifts rather than blindly applying division gives the reader at least some
reassurance that the original coder has given some thought to these matters.
A programmer with a limited vocabulary (i.e., is conversant with only a small number of idioms) is a programmer with a
limited vocabulary. How low shall we go in the sake of readability, that is, limiting our use of idioms?
Reply
david collier says:

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 10 of 23

August 31, 2011 at 6:36 am


eh? At the instruction set level there are at least 3 types of right shift
1 duplicate the new top bit from the old one
2 carry in zero
3 carry in something external
3 is unlikely to be generated by the compiler,
Does the C standard specify which of 1 or 2 is meant by >>
Reply
Trenton says:
August 31, 2011 at 7:53 am
@Does the C standard specify which of 1 or 2 is meant by >>
WG14/N1256 ISO/IEC 9899:TC3
6.5 Expressions
4 Some operators (the unary operator ~, and the binary operators <>, &, ^, and |, collectively described as
bitwise operators) are required to have operands that have integer type. These operators yield values that
depend on the internal representations of integers, and have implementation-defined and undefined aspects
for signed types.
6.5.7 Bitwise Shift Operators
5 The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a
signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If
E1 has a signed type and a negative value, the resulting value is implementation-defined.
Reply
david collier says:
September 2, 2011 at 6:46 am
thanks.
To summarise then either 1. or 2. will meet the specification, so C does NOT sepcify which of the
two will be used in some particular case.
which means Konrad was not correct with -1 >> 1 is -1, not 0. in fact the result is
implementation dependent.
Reply
15. Bruno Richard says:
August 31, 2011 at 3:01 am
About rule #5: I do not fully agree. Compilers will not optimize the constant variables away, and on small
microcontrollers this has an impact on the RAM or Flash consumption.
For example:
const unsigned short val = 10; // Will eat up 2 bytes of RAM on some compilers
You have to check what your specific compiler does.
My advice on this point is exactly the opposite: Use const variables on your large (Widows/Linux/OSX) projects, but
stick to #defines for constants on microcontroller projects!
Reply
Krzysztof Wesoowski says:
August 31, 2011 at 9:37 am

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 11 of 23

(From GCC experience)


You should declare this variable also static (so it can be optimized out by compiler), or enable -data-sections for
compiler and -gc-sections for linker, so linker will remove it.
If compiler is the only part that does optimization (as GCC before -flto), you must be careful when defining global
scope function/variables.
Reply
16. David Brown says:
August 31, 2011 at 3:02 am
I agree with most of this post, with a few comments.
I dont know where Mr. BadAdvices rules come from perhaps they are aimed specifically for a small and limited cpu
(my guess is an 8051) with a limited quality compiler. But if you have to follow his advice to get fast code, you should
invest in better tools (and better cpus). Oh, and dont forget to enable optimisations on the compiler (its amazing how
many people /do/ forget that!).
Bad rule #1 There are two more reasons to prefer divides to shifts. When you are dealing with signed data, it is no
longer easy to replace multiplication or division with shifts. It gets messy it is better to write the arithmetic operation
you actually want, and let the compiler sort out the details. Secondly, the compiler may be smarter about optimising
multiplication and division by constants than you are, especially for non powers-of-two. So I agree with you here write
the source code the way it should be written, and let the compiler optimise the implementation.
Bad rule #2 Again, I agree with your principle. is there for a reason, and its types should be used. int_fast8_t,
uint_least16_t, etc., are also useful, especially in portable code. Id go a little further than you, however, in that the
width of an integer /always/ matters, so the great majority of types used in a program should be from stdint.h. I also hate
the use of char when people are talking about a number a char is a character, or letter in a string. unsigned
char and signed char are totally meaningless concepts use uint8_t or int8_t as they are for numbers. I also hate
people who use unsigned or long as a type these are adjectives (and type qualifiers), not type names. Programs
should make sense when you read them just because the original C authors had crappy keyboards and had to take
shortcuts, does not mean modern programmers should follow their bad habits.
Bad rule #3 What is there to say, but that I agree? I suppose Mr. BadAdvice was using a small target cpu and a limited
compiler that generated inefficient code for >= and <=.
Bad rule #4 Again, I think BadAdvice must have a poor compiler any decent compiler will delay the initialisation
until it is useful, if it makes the code smaller or faster. But again I'd go further initialise every variable as soon as you
know its initial value, but don't declare any variable until close to when you need it, and within the smallest practical
scope. C99 has been around for a /long/ time the days of piles of variable declarations at the start of a function are
thankfully gone.
Bad rule #5 This is the only one I don't agree with entirely. Declare constants using "enum" when it makes logical
sense, with "static const" when possible, and with #define when necessary. There are some cases when you can't get
away with "static const" constants, such as array declarations. But always make sure you use "static const" rather than
plain "const" it tells the compiler that it knows every use of the constant, and can therefore optimise freely with it as
though it was a #define'd value. Without "static", the compiler must put the constant in memory and assume that some
other module will change its value unexpectedly. (Remember, C and C++ are different in this point in C++, "const" is
effectively "static const" by default.)
Reply
17. tomkawal says:
August 31, 2011 at 4:01 am
I would not argue when to use const,enum or define look always at the data representation, know your priorities.
But rulez which have no mean are ridiculous. I laugh and laugh at rule #3.
But there are issues with the hardware, the coders are rarely aware of:
Examples:
Naive coding:
If (++seconds == 60) seconds = 0;
Electronics designer code:
If (++seconds >= 60) seconds = 0;

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 12 of 23

I would like to post the recommendation: avoid ==, if you ca use >= or <='
Otherwise any spurious memory corruption will cause disaster.
I've seen the clock stuck at 65 seconds, as an example.
The first line of defence is good HW design for EMC, but second: proper plausibility checks in SW.
regards
Tomasz
Reply
david collier says:
August 31, 2011 at 6:38 am
UTC-leap-seconds-aware programmer code
If ( ++seconds >= num_seconds_in_this_minute ) seconds = 0;
Reply
18. david collier says:
August 31, 2011 at 6:42 am
Rule 1 is not a ruile. The rule should be
be aware that understanding the relationship between shifts and divisions ( or multiplications ) by 2 can sometimes give
you more efficient code.
I have a lovely block of code for an MSP430, which has a 12-bit AtoD. I DMA a block of AtoD values onto a buffer,
and then block add them to another buffer.
After doing this 16 times, the results are averaged 16-bit signed numbers I can use elsewhere.
If written without adequate comments its horrific. With the right comments its a thing of beauty.
Reply
19. Lundin says:
August 31, 2011 at 6:51 am
#1 is not really a programming rule, it is an optimization advise. There are actually still dumb-enough compilers around,
that will not do this shift optimization for you. So knowing about it is good, although it should only be used when one
has verified that 1) The compiler is indeed dumb and 2) that the division is an actual performance problem and not just a
non-existent problem conjured by the programmer.
I wouldnt call #1 bad nor good, it is just a commonly used optimizer trick.
#2 is generally a good rule. The rule doesnt say explicitly that the native primitive data types of C (int, char etc) should
be used. I think everyone agrees that either using stdint.h or typedef:ed integer types is a must, using the native primitive
types is a very bad idea for many reasons.
But the rule rather says: pick a size of the variable according to the need, which is another matter entirely. This is
especially important on small embedded systems (8- and 16-bit MCUs). On the other hand, on 32-bit or larger CPUs,
using anything but 32-bit integers is most of the time a bad idea, because as soon as you do you expose yourself to the
whole ballet of implicit promotion rules: one of the most dangerous features of the C language.
#3 is just strange. Why would you do that for? A common cause for bugs are programmers that assume that the logical
opposite of less than is greater than. While in reality, the opposite is greater than or equal. Anyone with a
software and/or electronics degree has likely been sufficiently exposed to boolean algebra and discreet mathematics to
understand this.
#4 is a very good rule for embedded systems! The main reason is that the C standard states that all variables that are
global or static must be initialized before use. Either to the value the programmer initialized them to, or if they didnt, to
the value zero. This initialization must be done before the program is started, it is required by the C standard. For an
embedded system where code resides in flash rather than RAM, this means that a copy-down snippet must be
executed in runtime before main() is called, which copies down values to all statics/globals.
This copy-down is very bad for several reasons. First of all, it means that as soon as your CPU hits reset, there will be
a startup delay while the copy-down is executed. This causes your program to start up much slower. Which in turn could
be disastrous if the program has some important code at top of main() that must be executed shortly after reset:

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 13 of 23

watchdog setup, low-voltage detect, clock initializations, pull resistor or I/O port enables, mode registers etc etc.
But the copy-down is also bad because it may very well take ages between the copy-down and the time when the code
using the variable is executed. During this time the value sits in RAM, and good practice is to never rely on RAM. High
integrity embedded systems typically forbids such practice, and also requires that all values in RAM are updated from
flash on regular basis.
To avoid all mentioned problems, it is common practice to write code that does not rely on static/global initialization, ie
the code does not rely on initialization at all. Most embedded compilers also have a non-standard option to disable
initialization at startup. If you wrote the code so that it does not rely on initialization, it will be portable even if this -very
- common non-standard extension is present in the compiler.
Ok so what if the variable is placed on the stack (auto) rather than static/global? The programmer must make sure to set
it at some point before using it. If they forget it well, it is no biggie. Since all professional programmers use static
analysers (right?), that will instantly find such simple bugs. Real programming rule standards like MISRA-C explicitly
states that all -automatic- variables should be initialized.
To sum this up, #4 is a very good rule for embedded systems. For RAM-based PC fluff however, it doesnt really make
any sense.
#5 is just personal preference, there is no real advantage/disadvantage to it. It isnt really worth debating.
To use enum to get -better- type safety is however a very bad idea! It is (signed) int by default, and thus it is as bad as
using the standard int type. And then comes all the dangers of implicit promotions again.
const and #defines can be declared unsigned, but enums cant.
Reply
David Brown says:
August 31, 2011 at 2:55 pm
Regarding #2, you misunderstood Michaels point. It is correct that you should often use a type that is no bigger
than you need, especially on small cpus (though be aware that on bigger cpus, code that accesses smaller types is
often slower). The point was that you should use uint8_t rather than unsigned char, etc.
Your comments on #4 show a misunderstanding of some basic C concepts. First, consider statically allocated data
(file scope, or function static data). Following the C standard, they must be initialised before main() starts either
to their specified initial value, or to 0. So if you omit the initialisation value, thinking to set it within the main
code, then the C startup library code will write 0 to the data. In other words, you wont save much time at the premain() stage, since the cpu will have to write 0 to the uninitialised data instead of copying in the real initial value.
And it is generally much more efficient (in time and space) to let the pre-main() routines initialise the data rather
than doing it explicitly in the main code.
If you have actions that must occur as soon as possible after reset, and cant wait for data initialisation, then most
embedded toolchains have hooks for adding your own pre-main() code. And anyway, youve probably got the
hardware wrong after all, reset and oscillator/pll startup typically takes longer than the pre-main() data
initialisation on most processors. So if you think you need something happening that fast after reset, the chances
are high that youll be getting startup glitches anyway.
For auto variables (on the stack, or in registers), C provides no automatic initialisation you need to do it every
time. If the programmer forgets it, then it /is/ a biggie the programmer has written incorrect code, and the
program wont do what it is meant to do. Most professionals use some sort of static analysis (or at least a compiler
with good warnings) but very few work by writing sloppy code and expecting the static analysis to spot the
bugs.
For #5, you are correct that C compilers treat an enum as an int (or unsigned int, long int, or unsigned long int if
necessary depending on the value of the enum constant) though some may be configured to use smaller types (in
the manner of C++). However, you may like to remember that a number literal (such as you get from #define two
2) is also considered an int (or unsigned int, long int, unsigned long int if necessary for its value). It makes no
difference.
Reply
Lundin says:
September 20, 2011 at 8:25 am
#2, no I did not misunderstand his point, I think this is pretty clear in my post.

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 14 of 23

#4 What misunderstanding of basic concepts? I wrote:


The main reason is that the C standard states that all variables that are global or static must be initialized
before use. Either to the value the programmer initialized them to, or if they didnt, to the value zero.
If you read this, you wouldnt have needed to repeat the very same explanation in your own post to educate
me about the things I had already written myself
My post explicitly mentions very common non-standard ways in embedded systems to skip mentioned
problems with static initialization. Adapting the code towards this non-standard extension is what my whole
text is about. If you read my post, I argue against using the C standard static initialization, since it is a bad
thing for the reasons mentioned in my post. But most importantly, if you write standard C code that does
not rely on static initialization, you can make your code insensitive to these non-standard extensions. This is
highly relevant for embedded systems design!
(Regarding those startup things that must be executed immediately, they are not necessarily time
consuming. Of all the things I mentioned in my post, the clock initialization is the only one with delay
potential, if you are using a PLL and not merely selecting some clock source or mode.)
Regarding sloppy code: personally I always keep track of every variable of my program there will be no
variable in my programs that I dont know what it does at any given time, it is a matter of discipline rather
than coding style. I never declare away a number of variables that seem good to have and then write the
program, I write the program and declare variables as I go, when needed. And I delete variable declarations
when I find that they arent needed.
Thus it is no biggie for me at least, I dont initialize auto variables to zero just in case I write a bug later
on. I dont see how that would be defensive programming, I just consider it bad practice. To set everything
to zero because you are counting on yourself to write bugs later on is not only strange, it will also
effectively hide away those possible later on bugs, so that they wont be caught during program
development, static analysis or not. Instead they will live all the way to production code, perhaps
completely disarmed by the zero-init, but bugs no less.
Anyway, I cant remember the last time I had a bug related to non-initialized auto variables. I dont think I
have written one of those since I was a beginner some 15+ years ago and I have only used static
analyzers in the later years, so at least to me this is a non-issue.
Reply
David Brown says:
September 28, 2011 at 7:58 am
If you understand that the C toolchain will initialise static data (to specified values, or to 0) before the
start of main(), then why do you go to such lengths to tell us that this is a bad thing, and to suggest it
can be avoided by leaving out initialisers?
Skipping this required initialisation is not very common though it is undoubtedly non-standard. I
know of only one tool that skips the zeroing of the bss and it is not known as Code Composter for
nothing. Any tool that does not require explicit settings to deviate from the standard behaviour is a
broken tool. So you dont need to write code that is insensitive to this extension if you want to
use such extensions, then you write code to suit it. If you want to write C code, then you write C
code. It is certainly /not/ good to suggest that we all write code that is slower and often less clear, just
in case someone wants to compile it with non-standard extensions.
If you have something that must be done so quickly after power-on that it cant wait for the
initialisation of global data (yet, bizarrely, is happy to wait for reset generator to finish and a PLL to
settle), then it should be handled in hardware using things like pull-up or pull-down resistors or other
logic. Skipping the initialisation of ram will not fix a broken design.
Incidentally, I am curious to your idea that high integrity systems forbid the reliance on RAM. How
do these high integrity systems store run-time data? What sort of systems exist where you consider
RAM so unreliable that you cant risk initialising a variable at startup, but are happy to do so a few
milliseconds later in code? High integrity means making sure your hardware suits the demands of
the system, and that you have some sort of check that the hardware works. So if you have a situation
where RAM is unreliable (such as high radiation environments), you use hardened RAM with ECC,
and probably redundant systems and majority voting. You dont try and write code on a system with
the assumption that that system doesnt work!

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 15 of 23

Regarding sloppy code I think you should re-read your original comment. I fully agree with you
that you should not thoughtlessly initialise local variables as a way to try to avoid bugs you should
initialise variables to the value you want when you want to use them. (And of preference you should
not define the variable until then, unless you are stuck with a pre-C99 compiler.) But what you wrote
was The programmer must make sure to set it at some point before using it. If they forget it well,
it is no biggie. Since all professional programmers use static analysers (right?), that will instantly find
such simple bugs. That sounds to me like you are suggesting its okay to write bad code and let the
static analyser find the mistakes rather than setting the variables value correctly when it is needed.
Reply
Petr says:
September 28, 2011 at 1:02 pm
Rule #2
What are the dangers of integer promotions?
Unsigned types are zero-extended (so 0xFF becomes 0x00FF), signed types are sign-extended (so -1
becomes -1), like one would expect.
Rule #4 Initialization at startup:
A decent compiler (actually C runtime) has a nonstandard way to execute specified functions before
this initialization is done.
If C runtime does not allow that then editing linker scripts does the trick.
If it is not possible and C runtime allows suppressing the initialization then your main can call the pre
-init functions in C-runtime explicitly and then manually run function in C runtime to do the
initialization.
If user writes a function which relies on the initialization and there is a chance the init will not be
done for some reason then the he can add an assertion to the code.
Only few situations benefit from the pre-init code, it is foolish to want ordinary code to be prepared
for such situation given the available solutions and diagnostic.
Rule #4 & high-integrity:
It is easier to do a full reboot then to re-run initialization of libraries.
RAM usually contains larger amount of non-constant data then constant data, so reinitializing only
constants will improve little reliability.
Reply
20. Phil Ouellette says:
August 31, 2011 at 8:39 am
Rule #4 has some merit.
If you are coding for a microcontroller with a watch dog timer then your first line of code is usually to disable the WDT
until you are ready to turn it back on. If your compiler startup code spends too much time initializing variables then the
WDT interrupt can fire before your first line of code (turning off the WDT) is executed. I ran into this problem once and
it was a bear to figure out what was behind the intermittant startup problem.
Another valid reason for #4 is I prefer to have init functions that set all of the module level globals to a desired state. I
sometimes call these init functions again as a way of performing a partial warm boot. It just makes sense to have
initialization of these variables be under my direct control instead of happening behind the scenes.
I also tend to prefer #5 as well. I often have used quite complicated #defines used to calculate register values for things
like oscillator and timer registers based on human readable inputs (Crystal Speed, Clocks per Instruction etc). These
calculations only need to be performed at compile time and it is pointless to do this at run time.
Here is an example from an 8051 project I wrote years ago:
// System Timer definitions
#define OPCODES_PER_SECOND (CRYSTAL_SPEED/CLOCKS_PER_OPCODE)

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 16 of 23

// Timer 0 reload defined to create 33 ms interrupt rate (roughly 30 ticks per second)
#if (CLOCKS_PER_OPCODE == 12) // Compiled for emulator mode
#define TIMER0_RELOAD (0xFFFF TICK_RATE_MILLISECONDS * OPCODES_PER_SECOND/2000L)
#else
#define TIMER0_RELOAD (0xFFFF TICK_RATE_MILLISECONDS * OPCODES_PER_SECOND/1000L)
#endif
#define LOW_BYTE(w) ((w)&0xff)
#define HIGH_BYTE(w) (((w)>>8)&0xff)
Later I use this #defined value in the interrupt routine
//Reload Real time clock tick rate
TH0 = LOW_BYTE(TIMER0_RELOAD);
TL0 = HIGH_BYTE(TIMER0_RELOAD);
Sure I could have just hard coded the values, but if my processor speed changed I would have to manually recalculate
the timer reload values. This way all I have to do is change the CRYSTAL_SPEED definition and everything that is
effected by a change in crystal speed (baud rate generator, timer init value etc) are automatically set to the correct
values.
Reply
21. _d says:
August 31, 2011 at 10:30 am
You may do the same things with enums instead of macro definitions:
enum
{
//
TIMER0_RELOAD = 0xFFFF TICK_RATE_MILLISECONDS * OPCODES_PER_SECOND/1000L,
TL0 = HIGH_BYTE(TIMER0_RELOAD),
// .. etc
};
Only function-like HIGH_BYTE() and LO_BYTE() in your example need to be a macro. However, in C++0x you may
use constexpr functions instead.
Reply
22. Laz says:
August 31, 2011 at 3:54 pm
Regarding #5, some of you are refering to values within one source module, and others are refering to values that are
shared across the project, including compiling options. You cant use a static const across modules. You can use
encapsulation methods, but isnt that getting extreme?
For example, I would use #define PI (3.1415f) and put that in constants.h, which is included in all modules. As stated
here, I should create a static const in constants.c, containing a function called pi(), which would have a prototype shared
among all modules. A similar situation for system clock parameters. Possibly more correct, but thatd be diffcult for me
to adopt.
I only use enums for lists where the value doesnt matter, eg colors, or indices, and I use the resulting type checking to
make sure I dont cross-use them. Also useful for auto-sizing arrays.
#define for bits always, for reasons described above. These should be local to a module/driver anyway.
Reply
David Brown says:
August 31, 2011 at 4:21 pm
You can happily put static const definitions in a header file. Unless you do something odd like take the address
or change its value, the result will be at least as code space, data space and time efficient as using a #define value.
Its just like using static inline functions in a header instead of function-like macros.
Reply

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 17 of 23

Eric Wertz says:


August 31, 2011 at 8:48 pm
I have to totally disagree my empirical tests with GCC dont bear this out at all, at least not with the
default options. I will concede that there *might* be a set of compiler switches that may mitigate some or
all of these space/time artifacts (individually, or maybe together), but Im extremely skeptical that using all
of these constructions interchangeably A Good Thing(tm) in the vast majority of situations.
In fact I contend that specifying static const as you state is almost the worst construction one can come up
with from a space and time standpoint. With GCC, one gets space allocated for every datum specified as
static const in EVERY module that includes such a header file, whether any of declared data are used or
not. In addition to the data space penalty, one also gives up the ability to encode the constant as an
immediate operand in the instruction for small enough constants by removing their lexical constantness at
the site to be compiled.
In the end, it all comes down to what the worlds collective (if you care about portability) legitimate
compilers do today. I dont doubt that the very, very best compilers can minimize the impact of any
arbitrary, abstract construction AND if the toolchain has complete information about the entirety of the
code to be linked together but I think that thats by far the exception rather than the rule. Some of these
artifacts often cant be mitigated by anything but a very sophisticated tool chain.
Reply
David Brown says:
September 1, 2011 at 2:32 pm
What do you mean the default options? No one uses a compiler without any options certainly not
for embedded development. So if you use gcc (or any other compiler) without enabling any
optimisation flags, you get what you asked for the simplest, big, slow code generated from the most
literal interpretation of the source code.
If you use the compiler as it is designed its an optimising compiler, so enable the optimiser then
the static const will produce the same code, or perhaps better, as #define (including doing constant
folding, using immediate operands, using different instructions, pre-calculating the results, etc.). Nonstatic const will often produce similar code, since gcc assumes that the programmer follows the
rules of C (some compilers are more pessimistic), but it will additionally generate space for the
constant in ram or flash.
Try it and see most embedded programs are compiled with -Os, but you can use -O1 or -O2 if you
prefer, and use -Wa,-adchls to generate a listing file.
It is true that few compilers are as good at optimising as gcc, and many will generate poorer code for
the non-static const since they allow for the possibility that another module will change the value. But
if your compiler wont optimise a static const properly (when youve enabled optimisation, of
course), then it really is time to get better tools or to accept that your old tools generate slow code.
Reply
23. Mac H says:
September 1, 2011 at 4:59 am
Bad Rule # 3 (His good rule # 7) is not only a bad idea it is actually a terrible bug.
Consider this example:
//
// If we have enough of the life saving drug, administer it to save the patients life. Otherwise the patient will die.
//
if (AmountOfLifeSavingDrug >=MinimumAcceptableLevel)
{
AdministerDrugAndSavePatientsLife(AmountOfLifeSavingDrug);
}
According to this bizarre bug inducing rule, we should optimise it to be:

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 18 of 23

//
// Allegedly optimised (but fatally buggy) version which will kill the patient
//
if (AmountOfLifeSavingDrug >MinimumAcceptableLevel-1)
{
AdministerDrugAndSavePatientsLife(AmountOfLifeSavingDrug);
}
It looks fairly similar (if a little bizarre) but it can kill the patient.
Imagine the simplest possible case ; AmountOfLifeSavingDrug & MinimumAcceptableLevel are unsigned integers.
(Ill assume 16 bit integers for the sake of the example but the logic works for signed as well any size)
So, if we wish it to accept any level, then we set MinimumAcceptableLevel = 0 (Or, if the values were signed,
MIN_SIGNED_INT)
In the correct (and intended) version, this is:
if (AmountOfLifeSavingDrug >=0) < Always true
{
AdministerDrugAndSavePatientsLife(AmountOfLifeSavingDrug); 65535u) < Always false.
{
AdministerDrugAndSavePatientsLife(AmountOfLifeSavingDrug); < Patient Killed
}

Overall the advice in that blogpost was riddled with basic errors. (eg: 'char' is not '-128 to +127' .. it is processor (and
compiler!) dependant. It could be unsigned. It could even (on DSPs) be 32 bits the C standard permits it)
It was originally ten rules but it is down to eight now that errors have been pointed out.
I only hope that more will be eliminated before anyone starts taking this seriously.
Mac
Reply
24. Colin Walls says:
September 1, 2011 at 5:36 am
I am unable to find the original posting, but I have to agree with just about every word you say here. I am rather
frightened to hear that someone developing medical instruments has such perverse ideas.
Reply
25. Rubberman says:
September 1, 2011 at 12:25 pm
Rule #1 right on! Shifting for integer multiplication or division by 2 can by useful when every machine cycle counts,
but different processors handle wrapping and overflows/underflows differently. Caveat programmer!
#2 ditto always use appropriately typed variables an int can be anything from 8 to 64 bits, depending upon the
processor and compiler. Bad assumptions make for bad code.
#3 a good example of programming by intention. Make your code clear what your intent was. Even if you have to
maintain it yourself, it will help you remember what you meant in a particular situation.
#4 totally agree! My rule is to initialize all variables as close to the declaration (preferably in the declaration) as
possible. An assignment takes processor time. Initialization in a declaration instance, especially if the value is a
constant, can be handled by the compiler, hence has zero run-time overhead.
#5 using #defines instead of const typed global/local variables is old school for most of this. There are exceptions, but
I try to stay away from the #define structure when possible. The downside? The const variables do take up memory,
whereas #defines do not (generally). Each construct has its own uses. Just make sure they are appropriate for your
situation.
Reply
David Brown says:

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 19 of 23

September 1, 2011 at 3:04 pm


Rule #1 if every cycle counts, get a compiler that does a decent job (or learn how to use the compiler you have).
Dont do silly hand-optimisations like this. Write your source code in a clear logical manner, and let the compiler
generate optimal implementations. Compilers can do a better job of optimisation if you have written sensible
code, rather than such half-way optimisations. You do your job, and let the compiler do its job.
Rule #2 No one has argued against using appropriately sized types just against using C types like char and
short instead of explicitly sized types. Read the article!
Rule #4 The compiler will still need to generate code to initialise a variable you dont get something for
nothing. But if you have a global (or static) variable and initialise it in code rather than at the definition (not the
declaration), then the target needs to do twice the work it must first clear the variable to 0, then initialise it in the
code.
Rule #5 Again, for everyone who has failed to read the other comments, static const do not take up memory. I
wish Michael Barr had got this right in his post, so that we wouldnt have to go through it again and again.
Reply
26. Bill Collis says:
September 2, 2011 at 12:56 pm
It may be really easy for compiler writers to detect such power of two divisions and replace them with shift, but they
dont do this. and should not do so because the result is not the same. Lets suppose that we want to divide an int by 2. If
the value happens to me -1 then division will give 0 and a shift right arithmetic will give -1. Maybe this matters. Maybe
it doesnt. But no compiler should assume it doesnt matter.
Personally I dont find any of the 5 rules dangerous . Rather, I felt them to be irrelevant to the real problem of writing
reliable code. Some of the examples of bugs given above are not appropriate because you can still apply the rules
without bugs. Writing deliberately buggy code and blaming the rules is not helpful. But is this always true?
The trouble with so called coding standards is that they are a kind of unverified dogma. There is no assurance at the end
of the day that the restrictions placed on the poor coder really translate into superior code. Most of the rules are far too
widely drawn and it is quite possible that the efforts to comply actually lead to buggy code.
Example: MISRA says you cannot compare a float for equality with a constant. So one of my staff didnt test for
division by 0.0! The rules should allow comparison with small integers which have exact floating point representations.
I take issue also with David Brown who claims that static const do not take up memory. If that were true you could
not calculate its address as the standard demands. It would be a miracle if all my error messages didnt take up any
memory!
Reply
David Brown says:
September 4, 2011 at 7:51 am
static const data is not allocated any memory under normal circumstances, for the sort of usage being described
here as a replacement for #defined numeric constants. Of course a static const will be allocated memory if you
take its address (unless the complier can optimise the code to avoid it) thats just like local variables being held
in registers or optimised away unless you take their addresses and force them onto the stack. And as I said
before, static const will likely take memory if you fail to enable your compilers optimiser.
MISRA has lots of very poor rules, but do not compare a float for equality is a good one. It is very bad practice
to test for equality to 0.0 before a division the correct handling is to write your code so that the code path in
question is not run with invalid data. It is certainly wrong to think that testing for a denominator of 0.0 will
somehow magically make your code work you can be pretty sure that a very small denominator will cause an
overflow with equally bad results. So if you are unable to ensure that you dont call that code with invalid data,
your test will really be something like if (abs(x) < 0.0001) {}".
You are quite correct that following coding standards does not give any guarantee or assurance that code is
correct. But it does give a guarantee that certain classes of bugs are very unlikely, and it gives a guarantee of
consistency that makes it easier to avoid or spot many other types of errors.

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 20 of 23

You are also correct that poor coding standards can result in worse code as the programmer is forced to follow the
standard. This is the case with MISRA it has many rules that, IMHO, lead to worse code.
Reply
Lundin says:
September 21, 2011 at 5:00 am
Everything takes up memory, no numbers can be allocated in thin air. The optimization you describe will
merely move the constant from the const segment of NVM or RAM into the program code, where it will
reside together with the op codes. The total amount of used memory data+program will be the same.
Regarding the MISRA-C rant, I agree that MISRA is harmful for junior programmers. If you didnt know
that you cant compare a float with equality operators, then you arent competent enough to comprehend the
quite advanced MISRA document. You must have at least one professional senior programmer in the team
to use MISRA-C.
For professional programmers it is an excellent set of rules, save for a few strange ones that hopefully will
be fixed in the upcoming MISRA C3.
Reply
David Brown says:
September 28, 2011 at 8:20 am
No, you are wrong about the memory use of static const (or #defined values). When then compiler
can see these as immediate compile-time constants, they are almost always more efficient than a
constant value at a particular address in memory. When the compiler wants to use such a value, it can
load it directly into a register or even use it as an immediate operand in an assembly operation
(depending on the target cpu and the type of value). The value will take space as part of the program
code that much is correct. But if the value is in memory as an individual const, then the compiler
must generate an operation to load it into a register from memory that means that the address of this
const is included in the program code, while the const itself is in data memory (ram or flash). You
have approximately doubled the memory cost (depending on the target), and almost certainly slowed
the code.
On top of that, there is the missed optimisation opportunities that could make a much bigger
difference.
When doing embedded programming, if you are at all interested in the efficiency (time or space) of
your generated code, then it is important to understand the architecture of the target cpu, and to take
time to study the compilers generated assembly code for different types of source code. It is much
more effective than making up rules based on common sense.
Im sure you are able to help your junior programmers write reasonable code with MISRA. For my
own part, I will continue to flaunt MISRA rules when it leads to clearer, safer code, or more efficient
code without sacrificing clarity or safety.
Reply

Leave a Reply
Name (required)
Mail (will not be published) (required)
Website

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 21 of 23

Submit Comment

Barr Code
Michael Barr
Michael Barr is an expert on the design of software-powered medical devices and other embedded
computer systems. (full bio)

Pages
Contact Michael

Links

Recent Posts

Embedded C Coding Standard


Embedded C Quiz
Embedded C++ Quiz
Embedded Software Boot Camp
Embedded Software Training in a Box
Embedded Systems Articles
Embedded Systems Books
Embedded Systems Experts
Embedded Systems Glossary
Expert Witness Resume
My E-mail Newsletter
My EETimes Column
My LinkedIn Profile
My Twitter Feed

How to Combine Volatile with Struct


Where in the World is Michael Barr?
Trends in Embedded Software Design
Building Reliable and Secure Embedded Systems
Combining Cs volatile and const Keywords
Firmware Forensics: Best Practices in Embedded Software Source Code Discovery
Dont Follow These 5 Dangerous Coding Standard Rules
How to Enforce Coding Standards Using PC-Lint
Is (uint16_t) -1 Portable C Code?
How to Enforce Coding Standards (Automatically)

Recent Comments
Lundin on How to Combine Volatile with Struct
Jan Bennett on How to Combine Volatile with Struct
JoeS on How to Combine Volatile with Struct

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 22 of 23

David brown on How to Combine Volatile with Struct


Michael Barr on How to Combine Volatile with Struct

Tags
architecture baltimore bugs copyright delicious education

embedded engineering ethics firmware india

java linux motorhome netrino opensource outsourcing patents processors

programming realtime rss rtos safety

security standards startups trac trademarks trends

Categories

Coding Standards (22)


Efficient C/C++ (6)
Firmware Bugs (23)
RTOS Multithreading (26)
Uncategorized (31)

Archives

November 2012 (2)


April 2012 (1)
March 2012 (1)
January 2012 (1)
September 2011 (1)
August 2011 (1)
June 2011 (2)
May 2011 (2)
April 2011 (1)
March 2011 (4)
February 2011 (4)
January 2011 (1)
December 2010 (2)
November 2010 (6)
October 2010 (2)
September 2010 (2)
August 2010 (2)
March 2010 (5)
February 2010 (5)
January 2010 (5)
December 2009 (3)
November 2009 (4)
October 2009 (3)
September 2009 (4)
August 2009 (2)
July 2009 (1)
June 2009 (1)
May 2009 (1)
April 2009 (5)
March 2009 (9)
February 2009 (3)
January 2009 (4)
June 2008 (1)
April 2008 (3)
March 2008 (5)
February 2008 (5)
January 2008 (4)
December 2007 (2)

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

Dont Follow These 5 Dangerous Coding Standard Rules Barr Code

Page 23 of 23

November 2007 (1)


September 2007 (2)
August 2007 (1)
July 2007 (2)
June 2007 (4)
May 2007 (2)
November 2006 (1)
October 2006 (2)
September 2006 (5)
March 2006 (1)
January 2006 (1)
December 2005 (1)
December 2003 (1)
November 2003 (1)
September 2003 (1)
July 2003 (1)
June 2003 (1)
May 2003 (1)
April 2003 (1)
March 2003 (1)
February 2003 (1)
January 2003 (1)
December 2002 (1)
November 2002 (1)
October 2002 (1)
September 2002 (1)
August 2002 (1)
July 2002 (1)
June 2002 (1)
April 2002 (1)
March 2002 (1)
February 2002 (1)
January 2002 (1)
December 2001 (1)
November 2001 (1)
October 2001 (1)
September 2001 (9)

Embedded Gurus - Experts on Embedded Software


website by Accent Interactive

http://embeddedgurus.com/barr-code/2011/08/dont-follow-these-5-dangerous-coding-sta...

26-11-2012

You might also like