TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Dangerous Embedded C Coding Standard Rules (2011)

34 pointsby momo-reinaover 11 years ago

8 comments

kabdibover 11 years ago
Well, let&#x27;s see.<p>#1: Avoiding shifting versus doing division: Nope. Crappy compilers and bad architectures will yield bad results. Know what you&#x27;re doing.<p>#2: Use a typedef instead of a bare C type, then. Also, on many systems space is king (the last embedded system I wrote had 6 bytes left over in code space, and 16-bit operations were incredibly expensive and nearly unaffordable).<p>#3: Just make the code clear. This rule is lunacy.<p>#4: Well, maybe. Except that variable initialization can often be made quite compact by the runtime (e.g., an expansion of a compressed data segment into RAM), and so save you code space.<p>#5: Again, the compiler can screw you here. Also, it&#x27;s possible to take the address of a constant and have it be wiped out (for naïve implementations, anyway).<p>My basic rules:<p>#0: Don&#x27;t make assumptions. Know what the heck is going on, fractally. Look at the generated code.<p>#1: Be a responsible engineer. Design and code for production and testing, and for the next guy. This often means not being clever, but if you are being clever, be forthright about it and don&#x27;t leave your brilliance as a puzzle. (Don&#x27;t be clever just to be clever. That will get you fired, no foolin&#x27;).<p>#2: Avoid platitudes. Be wary of people who tell you not to use something, always, or to use a particular contruct, always. Be suspicious of code that follows someone else&#x27;s dogma. [I once worked with a code base where the engineer had used the ternary -- &quot;?:&quot; -- operator <i>everywhere</i> because he thought it was more efficient than using &#x27;if&#x27;. Of course it was just guesswork on his part and not only was his code a train wreck, but he had never measured his results. We fired that guy).<p>Embedded systems are just software, they&#x27;re not magical, they&#x27;re not (usually) that hard, and for some reason people are afraid of them. Some of my best moments in the industry have been writing these little things, they&#x27;re fun as hell.
评论 #6986889 未加载
评论 #6986266 未加载
sophaclesover 11 years ago
This is one of those blog posts where the comments&#x2F;discussion are really good - maybe even better than the article itself. I recommend reading the discussion on-page if you haven&#x27;t.
wtracyover 11 years ago
Another reason to pay attention to #2: Most CPUs perform simple arithmetic operations fastest on their native word size. On a 32-bit machine, addition and subtraction on 8-bit variables is probably slower than on 32-bit variables. (Often the hardware will transparently cast to 32 bits, perform the operation, then cast back to 8 bits.)<p>I&#x27;m not an authority on this topic, so I don&#x27;t want you to take away the message &quot;always use the machine word size&quot;. What I <i>do</i> want you to take away is that there are many cases where an &quot;obvious&quot; optimization is counterproductive in practice. Always start with simple, working code, and never optimize without benchmarking.
评论 #6987012 未加载
mcguireover 11 years ago
With regards to Bad Rule #3, &quot;Avoid &gt;= and use &lt;,&quot; if I saw<p><pre><code> if (speed &lt; 100) ... else if (speed &gt; 99) </code></pre> in code, my only response would be to question the author&#x27;s sanity.<p>But then, I question the sanity of C standards committee members all the time, specifically regarding his actual complaint related to Bad Rule #2 and unspecified-width integer types[1].<p>[1] <a href="http://www.netrino.com/Embedded-Systems/How-To/C-Fixed-Width-Integers-C99" rel="nofollow">http:&#x2F;&#x2F;www.netrino.com&#x2F;Embedded-Systems&#x2F;How-To&#x2F;C-Fixed-Width...</a>
评论 #6986016 未加载
optymizer1over 11 years ago
I&#x27;m not completely on board with #4 (initialization of variables). I agree that &#x27;declaring and then assigning a value&#x27; _within the same block_ vs &#x27;initialized declaration&#x27; has no speed gains, only downsides.<p>However, if the assignment can happen in a _different block_ (maybe inside an &#x27;if&#x27; block) you could save 1 memory write, depending on how many times the if condition is satisfied.<p>This obviously optimizes for speed at the expense of maintainability, and it&#x27;s for the programmer to make intelligent trade offs, but the fact is that one method is faster than the other.<p>Silly example that decrements &#x27;a&#x27; repeatedly if condition is non-zero:<p><pre><code> &#x2F;&#x2F;temp = 0 inside if block int dec(int a, int condition) { int temp; if (condition) { temp = 0; &#x2F;&#x2F;&lt;-- memory write depends on condition &#x2F;&#x2F;compute something here in a loop while (temp &lt; a) { a -= (temp++); } } return a; } &#x2F;&#x2F;temp = 0 at declaration int dec2(int a, int condition) { int temp = 0; &#x2F;&#x2F; &lt;-- memory write always executed if (condition) { &#x2F;&#x2F;compute something here in a loop while (temp &lt; a) { a -= (temp++); } } return a; } </code></pre> We can disassemble the output to verify that dec() will only write to memory if the condition was satisfied (see 400458), while dec2() will always write into temp (see 400482):<p><pre><code> # &lt;dec&gt; 400448: push %rbp 400449: mov %rsp,%rbp 40044c: mov %edi,0xffec(%rbp) 40044f: mov %esi,0xffe8(%rbp) 400452: cmpl $0x0,0xffe8(%rbp) # if (condition) 400456: je 400473 &lt;dec+0x2b&gt; 400458: movl $0x0,0xfffc(%rbp) # temp = 0 &lt;-- depends on condition 40045f: jmp 40046b &lt;dec+0x23&gt; # while 400461: mov 0xfffc(%rbp),%eax 400464: sub %eax,0xffec(%rbp) 400467: addl $0x1,0xfffc(%rbp) 40046b: mov 0xfffc(%rbp),%eax 40046e: cmp 0xffec(%rbp),%eax 400471: jl 400461 &lt;dec+0x19&gt; # loop 400473: mov 0xffec(%rbp),%eax # return a 400476: leaveq 400477: retq # &lt;dec2&gt; 400478: push %rbp 400479: mov %rsp,%rbp 40047c: mov %edi,0xffec(%rbp) 40047f: mov %esi,0xffe8(%rbp) 400482: movl $0x0,0xfffc(%rbp) # temp = 0 &lt;-- always executed 400489: cmpl $0x0,0xffe8(%rbp) # if (condition) 40048d: je 4004a3 &lt;dec2+0x2b&gt; 40048f: jmp 40049b &lt;dec2+0x23&gt; # while 400491: mov 0xfffc(%rbp),%eax 400494: sub %eax,0xffec(%rbp) 400497: addl $0x1,0xfffc(%rbp) 40049b: mov 0xfffc(%rbp),%eax 40049e: cmp 0xffec(%rbp),%eax 4004a1: jl 400491 &lt;dec2+0x19&gt; # loop 4004a3: mov 0xffec(%rbp),%eax # return a 4004a6: leaveq 4004a7: retq </code></pre> The above code was compiled with gcc 4.1.2 on amd64&#x2F;linux. gcc -O2 and gcc -O3 completely do away with the &#x27;temp&#x27; variable and generate fewer instructions.
评论 #6986350 未加载
评论 #6986997 未加载
deletesover 11 years ago
Completely agree with no. 5. After a year with C I realized that macros are only to be used as control structures for headers and ifdefs to enable compatibility.<p>If you need macros to hack C to enable some functionality not inherent to the language, you should change the approach or switch to a different language.<p>Also macros are usually used to &quot;speed up&quot; the code. You should never optimize before finding the real bottleneck in your code. And thus always use functions instead of macros.
评论 #6985524 未加载
评论 #6985876 未加载
__david__over 11 years ago
Even better rule: Know the limitations of your target processor and compiler and code accordingly.<p>Example 1: Some (bad) compilers just ignore the const keyword (and therefore treat consts like normal variables). Use #defines with these compilers (or get a better compiler).<p>Example 2: Some (older, smaller) processors don&#x27;t have an integer division instruction. Avoid division <i>at all costs</i> on these processors unless you are not worried about space or execution speed.
评论 #6985618 未加载
评论 #6985387 未加载
dllthomasover 11 years ago
Regarding division and shifts, one thing worth noting is that you can now (with C11) bust out static assertions to make sure no one changes the count and the shift incompatibly. It&#x27;s still probably not worth doing unless there&#x27;s a good reason to make sure that particular operation is a shift rather than a multiply.