Page 1 of 1

inline | macro

Posted: Fri Nov 12, 2010 6:24 am
by Dario
As far as I can tell the only difference is that with inline functions we have type checking, while with macros we preserve some space in memory...?

Here I used 'nop' just to visually separate each block of code in assembly.

Code: Select all

#include <stdio.h>

#define ADD(x,y) ((x)+(y))

int add(int a, int b)
{
        return a + b;
}

int __attribute__((always_inline)) inl_add(int a, int b)
{
        return a + b;
}

int main()
{
        int a, b, c;
        a = 3;
        b = 4;

        __asm__ ("nop");
        add(a,b);       
        __asm__ ("nop");
        c = ADD(a,b);
        __asm__ ("nop");
        inl_add(a ,b);
        __asm__ ("nop");

return 0;
}

Code: Select all

08048382 <inl_add>:
 8048382:       55                      push   %ebp
 8048383:       89 e5                   mov    %esp,%ebp
 8048385:       8b 45 0c                mov    0xc(%ebp),%eax
 8048388:       8b 55 08                mov    0x8(%ebp),%edx
 804838b:       8d 04 02                lea    (%edx,%eax,1),%eax
 804838e:       5d                      pop    %ebp
 804838f:       c3                      ret    

08048390 <main>:
 8048390:       55                      push   %ebp
 8048391:       89 e5                   mov    %esp,%ebp
 8048393:       83 ec 28                sub    $0x28,%esp
 8048396:       c7 45 fc 03 00 00 00    movl   $0x3,-0x4(%ebp)
 804839d:       c7 45 f8 04 00 00 00    movl   $0x4,-0x8(%ebp)
 80483a4:       90                      nop
 80483a5:       8b 45 f8                mov    -0x8(%ebp),%eax
 80483a8:       89 44 24 04             mov    %eax,0x4(%esp)
 80483ac:       8b 45 fc                mov    -0x4(%ebp),%eax
 80483af:       89 04 24                mov    %eax,(%esp)
 80483b2:       e8 bd ff ff ff          call   8048374 <add>
 80483b7:       90                      nop
 80483b8:       8b 45 f8                mov    -0x8(%ebp),%eax
 80483bb:       8b 55 fc                mov    -0x4(%ebp),%edx
 80483be:       8d 04 02                lea    (%edx,%eax,1),%eax
 80483c1:       89 45 f4                mov    %eax,-0xc(%ebp)
 80483c4:       90                      nop
 80483c5:       8b 45 fc                mov    -0x4(%ebp),%eax
 80483c8:       89 45 f0                mov    %eax,-0x10(%ebp)
 80483cb:       8b 45 f8                mov    -0x8(%ebp),%eax
 80483ce:       89 45 ec                mov    %eax,-0x14(%ebp)
 80483d1:       90                      nop
 80483d2:       b8 00 00 00 00          mov    $0x0,%eax
 80483d7:       c9                      leave  
 80483d8:       c3                      ret
But looking at linux's source macros are heavily used although many programmers discourage it's usage. Why?
Also, one more question not related to this one, why does compiler put lea instruction instead of add for addition?

Thanks!

Re: inline | macro

Posted: Fri Nov 12, 2010 7:47 am
by Solar
Dario wrote:As far as I can tell the only difference is that with inline functions we have type checking, while with macros we preserve some space in memory...?
No.

First off, it is up to the compiler whether it honors your "inline" or not. It is merely a hint to the compiler. Sometimes - for example when the address of a function is taken - you need a "real" function, and the compiler automatically creates it. You cannot take the address of a macro, and will get an ugly error message if you're lucky, and some really strange behaviour if you're not.

Second, a macro can suffer from the "multiple evaluation problem". A macro as trivial as your ADD() wouldn't, but if you're using one of the macro's parameters more than once it will get evaluated each time it is used - which can be disastrous if you call e.g. MACRO( ++i ). This can be protected against, e.g. by assigning the parameters to local variables once and then using the locals, but you lose type flexibility and some of the memory / speed advantage.

Third, a macro cannot return a value. You can make most macros evaluate to a value, but usually you cannot protect against multiple evaluation (see above) and return a value. You need to put the locals in {} as to not pollute the namespace, and whatever you do within the braces is lost once you've done it. You could clobber one of the parameters as a return value, but you'd be right back into the multiple evaluation problem. Or you add a dedicated "out" parameter, Pascal-like... but that's getting really ugly.

All told, inline functions are the much cleaner approach.

Re: inline | macro

Posted: Fri Nov 12, 2010 8:55 am
by Dario
All clear...thanks!