6
\$\begingroup\$

I have been doing my first serious work of programming these days. I have been exposed to a lot of code by different developers. One thing I find confusing is how do these developers decide when to use a macro definition and when to use a inline function. Both have essentially the same function, they place a certain code at the place they are called from. So is there some logic for selection or is it just at the whimsy of the developer?

(I am here talking about macros for functions and not constants).

\$\endgroup\$
  • 2
    \$\begingroup\$ You might get more detailed answers from stackoverflow for this kind of question. \$\endgroup\$ – pfyon Jan 1 '11 at 17:17
  • 2
    \$\begingroup\$ I had thought about posting it there, but I thought as this would be more specific to embedded systems I should post it here. \$\endgroup\$ – Rick_2047 Jan 1 '11 at 19:23
9
\$\begingroup\$

There are many benefits to inline functions over preprocessor macros:

  • Type checking. The compiler will complain if the arguments are of incorrect type.
  • No risk of multiple evaluation: macros can be dangerous when the argument is an expression, consider:

    #include <stdio.h>
    #define square(n) ((n)*(n))
    
    int main(void)
    {
        int x, i = 0;
        while (i < 10) {
            x = square(i++);
            printf("%d\r\n", x);
        }
        return 0;
    }
    
  • Can include multiple lines of code without trailing backlashes.
  • Inline functions have their own scope for variables and they can return a value.

Macros can be useful e.g. when concatenating tokens into code, so as to simplify some complex declarations.

Consider macros as just a dumb text replacement functionality. A good rule of thumb is to avoid function-like macros, unless there is no other viable solution.

It is a common misconception that inlining always equals faster code. Keep in mind, that every inlined call from more than one place adds up to code size. Premature optimization is not a virtue, even when working with the constrained resources of a microcontroller.

GCC interprets the inline keyword as a mere hint. There is no guarantee thet the function will actually be inlined. To have GCC inline your function regardless of optimization level, declare the function with the always_inline attribute:

void function() __attribute__((always_inline));
\$\endgroup\$
6
\$\begingroup\$

Inline functions may or may not be inlined by the compiler. Macros, on the other hand, are handled by the precompiler, and are thus guaranteed to be inlined (code replicated). Often one will use a macro for a short but complex operation to add readability to the code, without taking a performance penalty for a function call. For example:

#define SWAP(a,b)({a ^= b; b ^= a; a ^= b;})

... provides a way to swap variables a and b without a function call and without a temporary variable.

There's a stackoverflow question to the same effect (though not specifically about avr-gcc).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.