embedded software boot camp

Efficient C Tips #3 – Avoiding post increment / decrement

Friday, August 1st, 2008 by Nigel Jones

It always seems counter intuitive to me, but post increment / decrement operations in C / C++ often result in inefficient code, particularly when de-referencing pointers. For example

for (i = 0, ptr = buffer; i < 8; i++)
{
 *ptr++ = i;
}

This code snippet contains two post increment operations. With most compilers, you’ll get better code quality by re-writing it like this:

for (i = 0, ptr = buffer; i < 8; ++i)
{
 *ptr = i;
 ++ptr;
}

Why is this you ask? Well, the best explanation I’ve come across to date is this one on the IAR website:

Certainly taking the time to understand what’s going on is worthwhile. However, if it makes your head hurt then just remember to avoid post increment / decrement operations.

Incidentally, you may find that on your particular target it makes no difference. However, this is purely a result of the fact that your target processor directly supports the required addressing modes to make post increments efficient. If you are interested in writing code that is universally efficient, then avoid the use of post increment / decrement.

You may also wonder just how much this saves you. I’ve run some tests on various compilers / targets and have found that this coding style cuts the object code size down from zero to several percent. I’ve never seen it increase the code size. More to the point, in loops, using a pre-increment can save you a load / store operation per increment per loop iteration. These can add up to some serious time savings.

Next Tip
Previous Tip
Home

14 Responses to “Efficient C Tips #3 – Avoiding post increment / decrement”

  1. ashleigh says:

    I've had many long arguments with C programmers who insist that *ptr++ WILL ALWAYS be better / faster / whatever. And I've never come across a case yet where it unambiguously is so.Check the generated code!Avoiding these operators also makes the code much more readable.

  2. Mike Layton says:

    If you read K&R (the original C) you find that they were motivated to make the language as terse as possible–as I recall, to allow transmission at eg. 300 baud. I don't recall hearing a case where terse code is more optimal for space or speed (with or without optimization). Most of the time I'm adding code to insure optimization.

  3. Murray says:

    On GCC with an ARM7tdmi it seems to make no difference at all. However, if you use "uint32_t i;" or "register uint32_t i;" for your local variable declaration, you see a significant size reduction and a speed increase.

  4. MarkM says:

    PowerPC specifically has instructions that support an addressing mode (the “U” instructions) where pre-increment/pre-decrement is provided for free in the load/store instruction itself. There is no equivalent post-increment/post-decrement instruction.

  5. Lundin says:

    I can’t recall a CPU where this would actually matter for efficiency reasons. The real issue here is that *ptr++ may be hard to read. C’s operator precedence rules are far from obvious, and that’s the main reason you should avoid it.

    There’s also the issue with order of evaluation: if you write *ptr++, then you might be tempted to write the classic C bug *ptr = *ptr++, which relies on the implementation-defined order of evaluation (and is banned by MISRA-C). For this reason, professional programmers never use the ++ operator together with other operators ever.

  6. Raul says:

    Hi,

    Thank you for your great articles!

    The link to IAR website is broken. Can you fix it please? Thanks again.

  7. Kyle says:

    Hi,

    The link appears to be broken again! Can you fix it please?

    Thank you for all these great articles and resources!

  8. Kyle says:

    Hi,

    The IAR link appears to be broken again! Can you fix it please?

    Thank you for all these great articles and resources!

Leave a Reply