Barr Code
Bug-killing standards for firmware coding
Michael Barr
3/24/2009 3:09 PM EDT
I look back fondly on the five years I spent helping to produce compelling issues of this great magazine, especially the three and a half years I served as its editor-in-chief. However, I was an engineer first, continued to write embedded software while I edited the magazine, and never doubted I would return to full-time firmware development afterward, as I did in early 2005.
The practice of embedded software development was my first professional passion and remains my most important. But I also enjoy writing books and articles about the subject and am thankful to current Editorial Director Rich Nass for granting me space in this column. It is with genuine pleasure that I sit down to write to you again, my peers, about important ideas.
I have experienced a lot in the field of embedded systems design in the four years I have been away from writing. Much of my focus during this time, across projects ranging from Zigbee-powered security badges to FDA-regulated medical devices, has been on the development of a system of practical techniques to keep bugs out of firmware.
I plan to use this column to expound on what I've learned about keeping bugs out, in the hopes that what has worked at my company will work at yours.



azertyqsd
3/26/2009 4:57 AM EDT
Nice article.
About your rule #6: An even worse problem of the C standard is that the "char" type can be either signed or unsigned (depends on the compiler or the compiler settings).
This can lead to nasty bugs, which reproduce on one developer's machine but not the other (depending on compiler settings).
2 advices for this:
- Always set your compiler for "unsigned" char by default.
- Never use a "char" declaration, but always "signed char" or "unsigned char".
My $.02,
Bruno
Sign in to Reply
David Brown
3/26/2009 6:16 AM EDT
For rule #8, your example is bad - integer promotion will ensure that the uint8_t a is promoted to (int) 6, and int8_t b is promoted to (int) -9. The constant "4" is already an int (whether you like it or not), so the comparison will be done correctly as the programmer expected.
The advice is sound, however - be wary of mixing signed and unsigned numbers. Sometimes things won't work as expected, and sometimes you end up with unwanted promotions (if you add a uint16_t to a int16_t on an 8-bit processor, you'll not be pleased when the compiler follows the C standards rules and promotes then both to int32_t).
Sign in to Reply
Dale Shpak
3/26/2009 10:42 AM EDT
Great overview of good coding practices, however ...
your examples include a bug-causing practice that is related to your rule #1:
The Allman brace style should NEVER be used for languages that use braces for compound statements a semicolon for terminating statements.
During my nearly 30 years of C programming, I have debugged millions of lines of code and have encountered the following type of error many times:
while (condition);
{
/* Execute conditional code */
}
Of course, the the bug is the semicolon after the while (or if). It is very difficult to notice during code reviews. This bug is very unlikely to occur with the one-true-brace style since a ;{ would be highly visible:
while (condition);{
/* Execute conditional code */
}
It is because of the automated translation of Pascal texts to C texts and Pascal authors who switched to C that we have this dangerous practice of the Allman style.
The only valid reason to ever have a left brace on a line by itself is to limit scope.
I have converted hundreds of programmers after convincing them of the many advantages of the one-true-brace style. Once you switch, you will never go back.
Sign in to Reply
Peter House
3/26/2009 10:55 AM EDT
The matching brace style is superior to the one true brace style since it is easier for the programmer to see how the braces are matched throughout the development and maintenance of a program.
The one instance cited, elimination of ;{ does not override the deficits of this styles' deficiencies.
Block bracing makes for far more maintainable code than the one brace style as it makes the structure of your program far more visible on a line by line basis. White space in a program is your friend and having matching braces makes for easier determination of the correctness of code grouping.
We may have to agree to disagree on this one!
Sign in to Reply
Dale Shpak
3/26/2009 10:59 AM EDT
Back on my soap box:
Please don't counter my inarguable facts with the old "the left brace and right brace nicely line up with the Allman style and show me the scope of my loop". That "prettiness" argument died eons ago with the advent of context-sensitive editors that show you the matching brace.
With 1TB you get to see more of your code in the editor window, etc., etc.
Notably, the Sun Java style guide wisely uses one-true-brace.
Sign in to Reply
Dale Shpak
3/26/2009 11:14 AM EDT
Yes Peter, we will have to agree to disagree, although I strongly agree that white space is your friend. However, once you change to 1TB you will find that the structure of your code is probably more visible than it was with the Allman style, as long as you indent your code:
while (condition) {
indented code line 1
indented code line 2
}
The way to think of this is that the right brace ends the while. The indented code is obviously within the scope of the while. Since proper coding style requires that the while aways has a right brace on the same line (no single-line while statements), the structure of the code highly visible and completely unambiguous. It may take a while to get used to the 1TB mindset, but you will never go back. Trust me on this one.
Sign in to Reply
Dale Shpak
3/26/2009 11:18 AM EDT
Unfortunately, the web site didn't use my multiple spaces (vanilla html). Speaking of which: always set your editor to expand tabs into spaces so that people using other editors can see the structure of your code.
Sign in to Reply
PeterLob
3/26/2009 2:24 PM EDT
It is interesting to see how one's prior experience influences one's perception of what good coding style is. The first structured high-level language I used was PL/M-86, which -- if memory serves -- used "DO" and "END" to delimit blocks of code. I preferred to place the "DO" on a line of its own, but one of my coworkers did not. I occasionally had to review or debug his code, and I found it difficult to match a "DO" with its corresponding "END". So, when I made the transition to Pascal and later to C, I retained a preference for keeping the opening delimiter of a code block on its own line. I have debugged many lines of other people's code and have never found a bug like the one Dale describes. Such bugs are easily prevented if the coding style insists that controlling statements must always be on a separate line from the statement or code block they control, even if only an empty statement is needed.
A particularly obscure construct that seems to be part of the 1TB style is "} else {" all on one line. That not only makes it difficult to match curly braces in pairs, but also to match an "if" with its corresponding "else".
C was developed in the days when the teletype and similarly slow devices were used for input and, sometimes, also for code listings. Therefore, it includes a number of elements that allow for very terse code. Now that input devices are much faster and code listings tend not even to be generated or needed, good style should probably prohibit the use of many of those elements. For example, embedding an assignment in the condition of an "if" statement should be discouraged, as should the use of the pre- and post-increment and -decrement operators within the parameters being passed to a function or during pointer dereferencing. It takes more characters and more lines of code, but clarity is vastly improved, and many opportunities for bugs are removed.
Sign in to Reply
Dale Shpak
3/26/2009 2:55 PM EDT
Well said, Peter. But, you do get used to 1TB, even the "} else {" all on one line. I have used both styles and have no difficulty immediately recognizing scope, nesting, or if-elseif constructs. As a matter of fact, I find it easier to match "if"s to "else"s using 1TB. With 1TB it is also easier to notice that you have the start of a new "if-elseif" in code containing several "if-elseif" blocks since the new "if" will start the line and therefore stand out from all of those "} else if {" constructs.
For the history buffs, I believe that PL/M86 used named scopes (which would help to reduce bugs):
LABL1: DO;
body
END LABL1;
The important point is that, to date, I have yet to see an example where 1TB can introduce a bug that would be prevented by the Allman style whereas I gave an example of an actual bug that I have seen several times that would be avoided by 1TB.
For mission-critical code, any practice that reduces bugs should be employed, even if it only reduces a bug having a probability of 1e-6 to a probability of 1e-9. I therefore use 1TB.
Sign in to Reply
estearg
3/26/2009 8:06 PM EDT
I had exactly the same experience as Dale, regarding 1TB.
And just a few days ago I downloaded sample code from TI which contained the bug Dale mentions.
1TB apart, I liked the article very much. It shows the way to go.
Sign in to Reply
figurassa
3/27/2009 11:25 AM EDT
Rule #4 : Concerning the volatile keyword :
to solve this problem but a lot of embedded software is still written in plain C and using older compilers.
I have always tried my best to follow this rule. But recently, I have ran across some postings in the linux kernel mailing list and in other places where people were discussing the shortfalls of the volatile keyword. They advocate the use of things like memory barriers instead of volatile. From what I gathered, most of their concerns have to do with software running on more than a single CPU and I am seeing more of these devices in the embedded arena. The new C++ standard is defining
Have any of you folks put some thought into this? What do you think? Should we be moving away from volatile? What are you using instead?
Cheers
Sign in to Reply
Alex OD.
3/27/2009 12:36 PM EDT
Rule 5
It sure would be nice if the #if 0 ... #else ...#endif would be recognized by my IDE and be coloured so that I know it's not code. /*...*/ all goes green and comment like, so I know it's not the version I'm using today.
Hmm, there's probably a way to do it, CodeWright allowed me to set up keywords so Codewarrior must...
Sign in to Reply
ErikS
3/27/2009 1:56 PM EDT
Rule #4, re figurassa
Not only can there be issues with multiple CPUs but a lot of C compilers mishandle volatile in single CPU architectures. There has been some discussion of this on the Safety Critical mailing list from the University of York. See the following website and paper from the University of Utah for more information:
Website: http://www.cs.utah.edu/~eeide/emsoft08/
Paper: www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf
Based on this paper an additional part to rule 4 might be stated as: All volatile accesses (read and write) shall be performed via a function call (i.e. hidden behind a function call).
Cheers!
Erik Shreve
Sign in to Reply
Matt S.
3/27/2009 5:56 PM EDT
I'm one of those "line-saver" aka one-true-brace coders, and have been since I began coding C, Perl, etc. Other programmers have moaned-and-groaned and I've tried the Allman style(s) and am unable to make sense of the line-saver style. Finding the matching brace is simple; I can scan the opposite brace by placing the cursor on the first character of the function declaration and holding the down-arrow reach the opposite bracket which will be on the same column. It's so clean and easy ... I can't imagine any other way. THANK YOU DALE FOR VALIDATING ME!!! On another vein, however, my style also has the practice where 'if a brace isn't needed, and excluding it doesn't lead to potential confusion, don't include it!'
Example:
void func ( void ) {
if (foo) {
if (bar) {
bracketed
bracketed
} else if (foo2)
no bracket
} /* but include this one */
} /* this bracket directly below *.
Sign in to Reply
Matt S.
3/27/2009 6:00 PM EDT
Can't edit the post, so I'll fix it here:
Other programmers have moaned-and-groaned and I've tried the Allman style(s) and am unable to make sense of the Allman style.
(this website has a VERY POOR commenting system IMO)
Sign in to Reply
piyush_
3/30/2009 10:58 AM EDT
The exact types (u)intX_t are not always portable. Some architectures do not support all exact types e.g TI's C54, C55 DSP (which have good standard C compilers), there is no exact 8-bit types (minimum addressable unit is 16-bit). Some architectures may not support 64-bit types. So code written with assumptions of exact bit types may not be portable. Instead, using (u)int_leastX_t types in stdint.h is more portable. But it is important that developer keeps in mind that it is minimum X-bits when coding i.e nowhere should there be an assumption that it is exact X bits, only then it is truly portable not by simply using (u)int_leastX_t in places of (u)intX_t types.
Sign in to Reply
figurassa
4/1/2009 8:41 PM EDT
Rule #4, re ErikS
Thanks a bunch for the info. Real cool stuff.
Sign in to Reply
VladG2
4/2/2009 1:46 AM EDT
it's a quite reasonable a set of rules, and it is appeared I follow 9.5 of 10.
It's not principal to use braces right after else or next line.
If function is several pages long I consider as a bad style. Difficult to dead difficult to debug, sense of vomit if the code is not yours.
Prefixing pointers with pXX, makes your code more readable, and easier to debug.
Extra careful with static variables, in multi-threading it's call for trouble.
I thought MIRA has much more rules.
Sign in to Reply
JSharp
4/4/2009 1:15 PM EDT
I have long been convinced that coding style guidelines are efficent bug prevention tools, and yet they frequently fall into disputes about aesthetics or theology. In the faint hope of driving religious ferver out of firmware coding, I suggest that coding style standards are much more environmentally determined than is commonly acknowledged. What works well in a 100,000-line Windows app is not necessarily appropriate to a 1,000-line program for an embedded processor. Different levels of tool sophisitication, language implementation and intended end usage make the rules malleable and context dependent.
My point is that there are no universally applicable "good" coding rules. Each rule must be judged on the basis of its capacity for preventing defects THAT ARE LIKELY TO BE INTRODUCED INTO CODE. That depends on your compiler's syntax checking capability, the maturity of your development process, whether you require static analysis and so on in your particular project. A rule that doesn't prevent defects or that prevents defects that aren't ever encountered just ticks people off. Developers find such rules annoying, and they frequently rebel by ignoring all the rules -- just the opposite of what's intended!
So, get off the soap boxes about curly brace placement. In any given project, any given style might be demonstrably better for any number of reasons. What's really important is identifying those reasons and being flexible enough to adopt the style that best fits the project environment.
Learn your tools, define an efficient process, get right with your team mates and get to work!
Sign in to Reply
Gary Stringham
4/8/2009 12:59 PM EDT
Rule #3: The static keyword shall be used to declare all functions and variables that do not need to be visible outside of the module in which they are declared.
While static can be used to hide stuff, it is also used to expose stuff such as in this example:
char * convert_chars (const char * str)
{
static char newstr[100];
... /* Convert characters */
return (newstr);
}
Heavy-handed use of static could leave you more exposed than you want and it could consume more memory than necessary.
Sign in to Reply
Iowan
4/9/2009 9:12 PM EDT
Perhaps I should get over it, but I was really rather offended by the blatant plug for Michael's $100 coding standard book.
Sign in to Reply
mbrunk
4/16/2009 2:56 AM EDT
The argument that "This bug is very unlikely to occur with the one-true-brace style since a ;{ would be highly visible" is worthy of further thought.
In his article, Mr. Barr states that:
"Thus a key strategy for keeping the cost of firmware development down is to write code in which the compiler, linker, or a static-analysis tool can keep bugs out automatically--in other words, before the code is allowed to execute."
The citation of "a static-analysis tool" is critically important to keeping bugs out of source code. And there is no static-analysis tool better than PC-lint. Period.
In the following code (concocted for demonstration purposes--it compiles but does nothing):
int condition;
int main(void)
{
while ( condition );
{
/* Execute conditional code */
}
return 0;
}
PC-lint issues the following warning:
foo.c(4) : Info 722: Suspicious use of ;
It's these types of warnings flagged by PC-lint, and not by most compilers I know of (including gcc), that makes PC-lint a valuable and arguably indispensible part of any software development effort. A coding standard (or software development process, in general) should require the use of PC-lint and also require that all source code be free of PC-lint "warnings" (and the standard or process should be free to define what a PC-lint "warning" is, as long as it defines it in a way that is reasonable, preferably by consensus; fortunately, PC-lint is astronomically customizable, and lets you inhibit warning such as ignoring the return value from such functions as printf, for example).
Sign in to Reply
Bruce_
4/16/2009 6:08 PM EDT
The debate about 1TB vs Allman vs others really isn't about whether it helps while(); or makes it more maintainable. I've used both and the whole while(); issue hasn't really happened in all my years of reviewing millions of lines of code. (which simply proves nothing, amount of time coding can mean you did something the wrong way for a very long time. :) )
Personally, I would rather deal with the few-and-very-far-between while(); bugs with better readability of Allman style. That is a personable observation and it will be different with everyone.
Most of the time proponents of 1TB just like the fact they can cram more info on the screen. In the end, you just follow a coding standard that is agreeable with the team.
However, I think in this article it was pointing out to simply bracket always which isn't a bad rule but is overlay spacious and if you use Allman style, simple comparisons spread the code out too much.
Cheers
Sign in to Reply
CharlesMiller
4/30/2009 12:18 PM EDT
SlickEdit allows "conditional display" based in preprocessor defines. It will even allow you to scan for defines and set them individually (the excluded, "not defined" sections appear as outline blocks that you can expand on-screen).
I agree that color coding would be nice. Color coding with user-specified-in-the-editor preprocessor defines would be VERY nice.
Sign in to Reply
George65
5/12/2009 9:11 AM EDT
Regarding Rule #8 on signed vs unsigned and data widths: remember that the difference between two unsigned integers is ALWAYS unsigned. always.
Sign in to Reply
Forma
5/18/2009 6:55 PM EDT
Hi Dale,
I'm impressed of your experience and a fairly good point you've made.. but - actually - what you're suggesting,which is rather a 'cosmetic' - might ..or might not lead to better code -however during your career you must have came acros coding standards. These are not easy to avoid - and if a particular style is a 'company-standard' - you need to follow it - wheather you like it or not...
And even more - imagine, that even if your point is right - and if someone, who used Allman style will switch to one-true-brace style - he might actually end up introducing new bugs. The reason for that is that as humans - we (more - or less) get used to the code style we're using...And if, say - you're writing for many years with one style -you might find it much easier to analyze code that follows ith - than code any other style (which sometimes can even be much harder to read - especially if there's a lot of code to read and understand).
So actually switching just because 'someone is suggesting it as 'better'' - might cause more errors than following own practice.. (of course provided, that own style was not horrible/messy in the first place..or providing, that there was any style at all ;) )
Regards,
Lukasz.
Sign in to Reply
Forma
5/18/2009 7:18 PM EDT
>>Unfortunately, the web site didn't use my multiple spaces (vanilla html). Speaking of which: always set your editor to expand tabs into spaces so >>that people using other editors can see the structure of your code.
I don't agree with this one too.. As far as most standards I came across showed - most popular and reasonable was to put the tab as a fist indention - then followed by space.
The reason for that is, that e.g. with Allman style a statement like: (where spaces are spaces.. and ___ means tab)
___if(var == a ||
___ var2 == c)
______{
______while( ...)
________{
________}
______}
in the editor with identation set to 8 - would still be readable - as it was - with default 3 (of 4..or whatever value set when writing the code).. but only more -spread- for bigger ident values.. If you've used spaces - and again someone was trying to extend identation from 4 to 8 - to have his own expected 'visibility' or readability - he will end up waisting his effort of trying - as with spaces it would look exactly the same regardless of this setting..
..and white-space - it's only - and mostly for humans - I don't see any point of rising arguments against this - as this is obviously ignored by compilers though...
Sign in to Reply
Forma
5/18/2009 7:19 PM EDT
Yes.. seems that this wiki-interprets some of the chars uded.. yet - another try then ;)
___if(var == a ||
___ var2 == c)
______{
______while( ...)
________{
________}
______}
Sign in to Reply
Forma
5/18/2009 7:44 PM EDT
Ok., but regarding the article :)
I quite liked it - nice idea of rising / addressing important topics/potential issues.
I have a comments to:
>rule #6
>Whenever the width, in bits or bytes, of an integer value matters in the program, a fixed-width data type shall be used in place of char, short, int, >long, or long long. The signed and unsigned fixed-width integer types shall be as shown in Table 1.
Actually - I think just the other way around - unless reasonable - if these are be used - the compiler makes the code more efficient (aligning it according to the architecture - which avoids sometimes zero or sign-extending - if dealing with smaller sizes than the machine word of a particular HW).
And as reasonable I mean - e.g. if we need to save memory - char / u char (or whatever they are typedefed with) - might be still as effective as int - on either 8bit platforms.. or these which do have 8bit memory read commands (e.g. ARM ldrb).
Some of rules (e.g. Rule #8:) - are captured by most compilers - and generally it's a good practice to try to compile with the highest warning level - to get the most of it.
> Rule #9:
>Parameterized macros shall not be used if an inline function can be written to accomplish the same task.3
Well it's worth adding - that this, giving the type-checking in one hand.. implies that if a macro was used for a different types - the inlined function might need to be overloaded.. (or templated if in C++).
> The reliability and portability of code are more important than either execution efficiency or programmer convenience.
THis looks bizzare.. in most cases we want both: efficiency and portability.. they both can be achieved - at least to some extent (both: efficiency and portability balanced/optimized).
And actually - if the code is ment to be portable - as mentioned before as comment to #Rule8 - using fixed-width variables ONLY if there's a really need for that - provided these two to be met: efficiency and portability. Reliability is unquestionalbe.. and programmer convenience doesn't make sence to me: - if one doesn't understand what he's doing - he probably shoudln't do it at all!!!
Sign in to Reply
Forma
5/18/2009 8:02 PM EDT
I really like JSharp's response - thats a really good point: flexibility and common sense..instead of 'things that are said to be the best'..
Some tricks with brackets (e.g with Allman style) - might help a lot with debugging - certain debug tools.. (especially HW debuggign tools- which tend to be more complex from 'the kitchen side' (as the HW becomes more and more complex.. many cores.. / peripherals and so one..) - and a farily poor on the user size) It makes sometimes impossible to set a breakpoint in 1TB style code just 'anywhere' - and only because these tools won't allow you to do that.. not - because the style is wrong.. Well.. but you might never need to use these tools.. or set breakpoints - so bothering with coding style for that reason looses its sense..
Sign in to Reply
Forma
5/18/2009 8:21 PM EDT
Rule #4, re figurassa, EricS,
Hi,
With my experience with multicore-embedded programming (especially on SMP systems, where any code might be executing simultaneously on a different cpu core) - volatile is quite desirabe in many places. I didn't find any problems - using them on single-core versions.. but certainly they won't wreak - if you put them in a 'suspicious' places, (i.e. declaring variables that migh be accessed by a different task, which - in fact might be running on a different core - in this case -no optimisations/assumptions should be made by the compiler - so using volatile will suggest it, that a value should always be read from the memmory.
Memory barriers and atomic operations are other problem. - i.e. using volatile will only force the compiler to creaate a code that always accesses the memory.. but protecting this memmory from corruption of data - if it's shared by a different task - needs to be provided - either with locks (spinlocks.. semaphores.. mutexes.. or just atomics - whichever way is appropriate).
Memory barriers are used to avoid a sort of 'race-condition' which are result of out-of-order execution, i.e. the HW might re-order instructions, which - by some simple factors don't seem to be related - which migh result, that for one thread - the order of data / instructions might be different than for other. And memmory barrier - (depending of it's type/implementation etc)- is to ensure/enforce, that i.e. all following / preceding read/instruction fetches have beed completed - before / after the barrier exection - so that - e.g. the instruction following the barrier was executed in the desired order. New C++ standard was to ensure that.. so we'll see how it goes :)
Sign in to Reply
tehwalrus
6/19/2009 9:36 AM EDT
Sorry to contribute to the ongoing braces discussion - clearly an "agree to disagree" issue - but I have to say that this one true brace nonsense hurts my eyes! How are you supposed to see the code blocks?
I am especially embittered against the
} else {
structure as it kills both the blocks and the if..else if..else flow, visually, and when reading other people's code (particularly open source java projects for some reason) I can only just stop myself shouting at the TFT: why haven't these guys even /read/ the...internal company coding standards. I see.
And whoever said that auto code highlighting solves all the problems has clearly never seen what happens when you are modifying the block - the parser decides that the wrong braces are paired and throws you off! You need the indentation
just to compensate for it's foolishness!
...in my opinion. I am sure that "everyone in the venture doing the same" is more important than which people choose though (even though I have a person preference I can invent reasons for), as coding standards aren't standards if half of you do it one way, half the other, and there's a guy who doesn't believe in whitespace.
Edited by: ESD editorial staff: SRambo on Apr 1, 2010 11:49 AM
Sign in to Reply
jmdavid1789
7/3/2009 2:47 PM EDT
Your rules are not too bad. I am saying not too bad rather than good because they have been accepted (or tolerated if that is not your style) for a while.
I take part in our code review process and I noticed that our disagreements are more on the PATTERN level rather than on the SYNTACTIC one (I.e. instruction level like with your rules).
- So I am asking whether Netrino has a pattern standard in addition to their coding standard? Or is it included in the coding standard?
I am quoting an example with a simple pattern:
My objection was that the for(;;) is the pattern of an infinite loop. But that case is not an infinite loop. Therefore it is misleading then difficult to maintain.Therefore rejected in the review process and should be replaced by while(EOK != err){
My colleague argued that it is working, it has been like that for a long time and used many times (I am quite new in the company) and that our coding standard does NOT mention that as a rejection (in fact, it does mention the case at all!)
Well, I had to accept and tolerate.
- My question to the community is: how to you arbitrate when the disagreement is on the pattern level rather than on the syntactic level?
Edited by: ESD editorial staff: SRambo on Apr 1, 2010 11:50 AM
Sign in to Reply
D_Lundin
8/11/2009 4:05 AM EDT
These rules seem to have a strong focus on petty syntax issues. Those are rarely the source of problems in modern C programming. For example the (0 == x) rule... this was preached thirty years ago. Is there a single modern compiler not giving "possibly incorrect assignment" warning for "if(x = 0)"? Even ancient Borland Turbo warned the dinosaurs for this mistake.
Focus on the important parts in MISRA-C instead: writing portable code and understanding the C language. The introduction of a "int8" type is unfortunate. The main reason for enforcing integer typedefs is to avoid problems caused by implicit signedness of integers, which is a much larger hazard than wrong integer sizes. "int", "char" etc could have any sign, just as integer constants typed out in the code can have any sign. A "int8" type could easily be misinterpreted. MISRA-C enforces sint8_t and uint8_t.
A main concern related to the above, addressed by MISRA, is that a frightening amount of the so-called C programmers don't know about the integer promotion rules. The example in rule #8 suggests that the author of the article is one of them:
uint8_t a = 6u;
int8_t b = -9;
if (a + b < 4)
Because of the integer promotions in C, both a and b will be promoted to the "int" type which may or may not be signed. We don't know which, it is implementation-defined behavior. The compiler's implementation of "int" will therefore determine the outcome of that if-statement. Most likely it will be signed, and then the code will work as expected, though we can never assume that "int" is signed.
Sign in to Reply
D_Lundin
8/11/2009 4:06 AM EDT
These rules seem to have a strong focus on petty syntax issues. Those are rarely the source of problems in modern C programming. For example the (0 == x) rule... this was preached thirty years ago. Is there a single modern compiler not giving "possibly incorrect assignment" warning for "if(x = 0)"? Even ancient Borland Turbo warned the dinosaurs for this mistake.
Focus on the important parts in MISRA-C instead: writing portable code and understanding the C language. The introduction of a "int8" type is unfortunate. The main reason for enforcing integer typedefs is to avoid problems caused by implicit signedness of integers, which is a much larger hazard than wrong integer sizes. "int", "char" etc could have any sign, just as integer constants typed out in the code can have any sign. A "int8" type could easily be misinterpreted. MISRA-C enforces sint8_t and uint8_t.
A main concern related to the above, addressed by MISRA, is that a frightening amount of the so-called C programmers don't know about the integer promotion rules. The example in rule #8 suggests that the author of the article is one of them:
uint8_t a = 6u;
int8_t b = -9;
if (a + b < 4)
Because of the integer promotions in C, both a and b will be promoted to the "int" type which may or may not be signed. We don't know which, it is implementation-defined behavior. The compiler's implementation of "int" will therefore determine the outcome of that if-statement. Most likely it will be signed, and then the code will work as expected, though we can never assume that "int" is signed.
Sign in to Reply
George65
9/10/2009 2:57 PM EDT
One bug that surprised me was finding out that "the difference between two unsigned integers is unsigned"
It is obvious now, but has obviously ominous consequences when not recognized.
Sign in to Reply
David_Giles
9/23/2009 7:35 AM EDT
A good static analysys tool will pay dividends when trying to identify bugs in software. A 'unit testing' tool, will also be able to identify bugs when actually running the code also, which is why they are mandatory for high reliability applications such as aerospace. for those interested in Unit Testing and writing cleaning code then have a look at the two seminars we have planned on this topic, in about three weeks time.
www.hitex.co.uk/seminar
Sign in to Reply
D_Lundin
9/24/2009 10:25 AM EDT
"One bug that surprised me was finding out that "the difference between two unsigned integers is unsigned"
This depends on the type of integers, because of the integer promotion rules in C.
unsigned int minus unsigned int will always yield an unsigned int. Same for unsigned long.
unsigned short minus unsigned short will yield an int which you don't know whether it is unsigned or not.
Sign in to Reply
srbohra
12/16/2009 5:46 AM EST
I know Peter it is not write place to ask but I find net extensively then even I found very less info about PL/M-86 due it is older language.
So I ask my question to you at this place pls don't mind it..
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
My Problem is :-
I have a PL/M-86 complier [DOS 5.0 (038-N) PL/M-86 V3.1]. ***This generates assembly code***.But to run this assembly code i required some tool which i don't have till now. If you have any exprience in PL/M code run or debug then please share with me. Someone told me that to run plm code sequece is
[code]-----compile--->>[.obj file]-------link---->>[.lnk file]-----locate--->>[Locatable file which can burn on rom]
+ + +
[.lst file] [.mp1 file] [.mp2 file]
(1) (2) (3) (4)
***At step (2) I got some part of assembly code which i stated above.***
This is whole stituation. Now say what can i do for debugging or run my PL/M code.
(Please answer in detail form that i can understand)
Sign in to Reply
groovyd007
7/9/2010 8:46 PM EDT
Question of the year...
When will someone please bump C/C++ up to D let's say and do away with both semi colons and curly braces for once and for all just like python? I cannot imagine a cleaner code style to read. As well I love how it forces indentation on the coder.
I don't need any more changes in D than this, just take C/C++ and remove the semi-colons and braces please, someone. I would even pay someone to write me a cross-compiler front end to do this for me.
Sign in to Reply