Electronic – Macros V/S inline functions while programming for avr-gcc

avravr-gccc

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).

Best Answer

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));