inline functions vs. macros

Discussion in 'C Programming' started by Robert Seacord, Oct 18, 2006.

  1. When writing C99 code is a reasonable recommendation to use inline
    functions instead of macros?

    What sort of things is it still reasonable to do using macros? For
    example, is it reasonable to write type generic functions macros?

    #define CUBE(I) ( (I) * (I) * (I) )

    Is there some more concise set of things where inline functions should
    be used instead of macros? Multi-statement macros, for example?

    Thanks,
    rCs
    Robert Seacord, Oct 18, 2006
    #1
    1. Advertising

  2. Robert Seacord

    Ben Pfaff Guest

    Robert Seacord <> writes:

    > Is there some more concise set of things where inline functions should
    > be used instead of macros? Multi-statement macros, for example?


    In general, if an inline function can be used, it should be
    used. Inline functions are much less likely to cause nasty
    surprises than macros, so they are preferred.
    --
    "The fact that there is a holy war doesn't mean that one of the sides
    doesn't suck - usually both do..."
    --Alexander Viro
    Ben Pfaff, Oct 18, 2006
    #2
    1. Advertising

  3. Robert Seacord

    Darko Guest

    Well, as the majority probably know, macros are really tricky to use
    and one should be very careful with them. The best example I know when
    they shouldn't be used, is the following:

    #define max(a,b) ((a)>(b)?(a):(b))
    int x = 4, y = 5;
    int z = max(x++, y++);

    One would expect the x and y to be incremented once each, but the fact
    is the text renders into the following:
    int z = ((x++)>(y++)?(x++):(y++)),
    which means the bigger of the two will get incremented twice instead of
    only once.

    Robert Seacord wrote:
    > When writing C99 code is a reasonable recommendation to use inline
    > functions instead of macros?
    >
    > What sort of things is it still reasonable to do using macros? For
    > example, is it reasonable to write type generic functions macros?
    >
    > #define CUBE(I) ( (I) * (I) * (I) )
    >
    > Is there some more concise set of things where inline functions should
    > be used instead of macros? Multi-statement macros, for example?
    >
    > Thanks,
    > rCs
    Darko, Oct 18, 2006
    #3
  4. Robert Seacord wrote:
    > When writing C99 code is a reasonable recommendation to use inline
    > functions instead of macros?


    In cases when the both methods are interchangeable - of course, using inline
    functions is a better idea.

    > What sort of things is it still reasonable to do using macros?


    There are lots of things that can only be done with macros. Macros can be used
    as a substitute for absolutely any piece of code and that means a lot.

    For example, one can use macros to generate object and function declarations and
    definitions. One can use macros to implement "local functions" (repetitive
    pieces of code that have access to automatic variables from the enclosing
    scope). Functionality of macros can be used to simulate functionality of
    templates in C++.

    When macros are used to implement "functions" they can be made to support
    certain form of "lazy calculation". For example, the following macro

    #define SELECT(s, v1, v2) ((s) ? (v1) : (v2))

    will calculate only one of the two expressions depending on the selector's value
    (cannot be achieved with an inline function).

    And so on. Again, there are lots of other things that can only be done with
    macros. One just have to keep in mind that benefits of macros often come with a
    considerable number of drawbacks, meaning that one has to use macros with
    caution. Nevertheless, the popular belief that macros should be avoided at all
    costs makes absolutely no sense. But in situations where macros and inline
    functions offer the same functionality it is better to stick with inline functions.

    > For
    > example, is it reasonable to write type generic functions macros?
    >
    > #define CUBE(I) ( (I) * (I) * (I) )


    Well, if the key point here is to have a type-generic "function", then it is
    reasonable. However, in a simple case like this it might prove to be a better
    decision to just write several inline functions with different names. Actually,
    macros can still be used to do the latter as shown below:

    #define DEFINE_CUBE(T, s) inline T cube_##s(T v) { return v * v * v; }

    DEFINE_CUBE(double, d)
    DEFINE_CUBE(int, i)
    DEFINE_CUBE(unsigned, ui)

    --
    Best regards,
    Andrey Tarasevich
    Andrey Tarasevich, Oct 18, 2006
    #4
  5. Darko said:

    > Well, as the majority probably know, macros are really tricky to use


    I agree that macros do require a modicum of care, particularly if their
    arguments are evaluated more than once, but I wouldn't go so far as to say
    they're really tricky. Yes, okay, you can /make/ them tricky, but then you
    can make functions tricky, too.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
    Richard Heathfield, Oct 18, 2006
    #5
  6. Robert Seacord wrote:
    > When writing C99 code is a reasonable recommendation to use inline
    > functions instead of macros?


    They're apples versus kittens. About all they have in common is
    they're both edible.

    With a macro you're assured it's going to get expanded as text right
    there. Now is it assured an inline function will get expanded inline?

    With a macro you can call it in any context, with or without parens,
    and it will generate almost any syntactical mess. A function can only
    be used in certain contexts, executable, and must have parens.

    macros have their place when you need some bizarre declaration or
    executable code.
    For instance since C doesnt have a "with" statement, you have to write:

    Application->WindowList[ Message->WindowIndex ]->Next->Panel->Title =
    "syph";
    Application->WindowList[ Message->WindowIndex ]->Next->Panel->Font =
    "Aramaic";
    Application->WindowList[ Message->WindowIndex ]->Next->Panel->Style =
    S_BOLD;
    Application->WindowList[ Message->WindowIndex ]->Next->Panel->Align=
    AA_RIGHT;

    .... which just cries out for some factoring. One way is to (ouch) use
    a macro.
    Ancient_Hacker, Oct 18, 2006
    #6
  7. Robert Seacord

    John Bode Guest

    Robert Seacord wrote:
    > When writing C99 code is a reasonable recommendation to use inline
    > functions instead of macros?
    >
    > What sort of things is it still reasonable to do using macros? For
    > example, is it reasonable to write type generic functions macros?
    >
    > #define CUBE(I) ( (I) * (I) * (I) )
    >


    It is, until someone innocently writes

    x = CUBE(y++);

    and gets undefined behavior for their trouble.

    > Is there some more concise set of things where inline functions should
    > be used instead of macros? Multi-statement macros, for example?
    >
    > Thanks,
    > rCs


    Remember that the C preprocessor is strictly a text substitution
    mechanism; it does not know or care about scope, or type, or syntax, or
    anything else. Therefore, using preprocessor macros to simulate inline
    functions or to fake generic programming is generally a bad idea for
    anything other than the most simple of expressions, and even then you
    have to beware of situations like the one I describe above.

    If you need a function-like operation, then use an actual function,
    whether it's inline or not. If you're concerned about efficiency, use
    a profiling tool to find the real bottlenecks; don't just blindly
    convert functions to macros in the hopes that it will speed things up.

    If you want generics, use C++ or some other language that supports
    them. Trying to fake it in C is often more trouble than it's worth.
    John Bode, Oct 18, 2006
    #7
  8. Robert Seacord

    Ian Collins Guest

    Ancient_Hacker wrote:
    > Robert Seacord wrote:
    >
    >>When writing C99 code is a reasonable recommendation to use inline
    >>functions instead of macros?

    >
    >
    > They're apples versus kittens. About all they have in common is
    > they're both edible.
    >
    > With a macro you're assured it's going to get expanded as text right
    > there. Now is it assured an inline function will get expanded inline?
    >
    > With a macro you can call it in any context, with or without parens,
    > and it will generate almost any syntactical mess. A function can only
    > be used in certain contexts, executable, and must have parens.
    >
    > macros have their place when you need some bizarre declaration or
    > executable code.
    > For instance since C doesnt have a "with" statement, you have to write:
    >
    > Application->WindowList[ Message->WindowIndex ]->Next->Panel->Title =
    > "syph";
    > Application->WindowList[ Message->WindowIndex ]->Next->Panel->Font =
    > "Aramaic";
    > Application->WindowList[ Message->WindowIndex ]->Next->Panel->Style =
    > S_BOLD;
    > Application->WindowList[ Message->WindowIndex ]->Next->Panel->Align=
    > AA_RIGHT;
    >
    > .... which just cries out for some factoring. One way is to (ouch) use
    > a macro.
    >

    Or
    PanelType *panel =
    &Application->WindowList[Message->WindowIndex]->Next->Panel;

    --
    Ian Collins.
    Ian Collins, Oct 18, 2006
    #8
  9. Robert Seacord posted:

    > When writing C99 code is a reasonable recommendation to use inline
    > functions instead of macros?



    Not in general, no, for three reasons:

    (1) C90 doesn't support inline.
    (2) Even if the compiler _does_ support inline, the code is guaranteed to
    be inlined.
    (3) It doesn't yield a compile-time constant.


    > What sort of things is it still reasonable to do using macros? For
    > example, is it reasonable to write type generic functions macros?



    Yes, it's grand.


    > #define CUBE(I) ( (I) * (I) * (I) )



    This one evaluates its argument more than once, but that's OK since the
    macro name is in ALL CAPS, which serves as a warning to the programmer.


    > Is there some more concise set of things where inline functions should
    > be used instead of macros? Multi-statement macros, for example?



    If you need to define variables _and_ return a value, you might need a
    function.

    --

    Frederick Gotham
    Frederick Gotham, Oct 18, 2006
    #9
  10. Frederick Gotham <> wrote:

    > (1) C90 doesn't support inline.
    > (2) Even if the compiler _does_ support inline, the code is guaranteed to

    ^^ isn't
    > be inlined.
    > (3) It doesn't yield a compile-time constant.


    A macro might not either; much good and evil can be done with macros.

    --
    C. Benson Manica | I *should* know what I'm talking about - if I
    cbmanica(at)gmail.com | don't, I need to know. Flames welcome.
    Christopher Benson-Manica, Oct 18, 2006
    #10
  11. On Wed, 2006-10-18 at 21:16 +0000, Frederick Gotham wrote:
    > Robert Seacord posted:
    >
    > > When writing C99 code is a reasonable recommendation to use inline
    > > functions instead of macros?

    > Not in general, no, for three reasons:
    >
    > (1) C90 doesn't support inline.
    > (2) Even if the compiler _does_ support inline, the code is guaranteed to
    > be inlined.


    You meant /not/ guaranteed to be inline. According to C99, that is.

    --
    Andrew Poelstra <http://www.wpsoftware.net/projects/>
    Andrew Poelstra, Oct 18, 2006
    #11
  12. Robert Seacord

    Pedro Graca Guest

    Darko top-posted [reordered]:
    > Robert Seacord wrote:
    >> When writing C99 code is a reasonable recommendation to use inline
    >> functions instead of macros?

    >
    > Well, as the majority probably know, macros are really tricky to use
    > and one should be very careful with them. The best example I know when
    > they shouldn't be used, is the following:
    >
    > #define max(a,b) ((a)>(b)?(a):(b))
    > int x = 4, y = 5;
    > int z = max(x++, y++);
    >
    > One would expect the x and y to be incremented once each, but the fact
    > is the text renders into the following:
    > int z = ((x++)>(y++)?(x++):(y++)),
    > which means the bigger of the two will get incremented twice instead of
    > only once.


    And if you had defined your macro in ALL UPPERCASE, someone writing

    int z = MAX(x++ .... hey! it's MAX in all uppercase
    .... must be a macro, let me do it like this instead

    x++; y++;
    int z = MAX(x, y); /* wheew! good thing the original programmer
    used ALL UPPERCASE for this macro :) */

    --
    File not found: (R)esume, (R)etry, (R)erun, (R)eturn, (R)eboot
    Pedro Graca, Oct 18, 2006
    #12
  13. Robert Seacord

    Guest

    Robert Seacord wrote:
    > When writing C99 code is a reasonable recommendation to use inline
    > functions instead of macros?


    For the purposes of portability or long term viability/maintainability,
    use of C99 is *not* a reasonable recommendation. You should use C
    compilers that will have long term support, or otherwise write code to
    the lowest common denominator (portable C/C++.)

    Keep in mind that "static" function declarations are usually basically
    equivalent to what is intended by C99's "inline". For serious
    compilers, there should be no effective difference between the two
    (inline further asserts that taking the address of the function is
    illegal, however, a static function whose address *isn't* taken (which
    it can always determine because it *is* static) becomes equivalent in
    functional status.)

    > What sort of things is it still reasonable to do using macros? For
    > example, is it reasonable to write type generic functions macros?
    >
    > #define CUBE(I) ( (I) * (I) * (I) )
    >
    > Is there some more concise set of things where inline functions should
    > be used instead of macros?


    The general rule of thumb that I use is that complicated macros should
    be module local and commented (or obvious). Otherwise, macros should
    be limited to constants, or convenience wrappers.

    > Multi-statement macros, for example?


    There's the whole issue of if() else and multi-line macros. The way
    you can get around it is to wrap your multi-line macro with a do { ...
    } while(0);. Unfortunately many compilers complain that the while (0)
    condition is constant and issue a warning. I don't like turning this
    warning off in the compiler, because its reasonable if the "0" comes
    from some compiler simplifications. So we're kind of in a no-win
    scenario here.

    Sometimes some kinds of multi-statement macros can lead to interesting
    conundrons. Suppose we have the following macro:

    #define hf_idxFirst(t,i) {\
    i = hf_NOT_FOUND;\
    if (NULL != (t)) hf_idxNext(t,i);\
    }

    This is fine, except that you cannot write code such as this:

    for (hf_idxFirst (table, i); !hf_idxIsEnd(table,i);
    hf_idxNext(table,i)) {
    /* ... */
    }

    This isn't so much a multi-statement macro issue as much as a control
    code fragment limitation issue that gets hidden by a macro.

    --
    Paul Hsieh
    http://www.pobox.com/~qed/
    http://bstring.sf.net/
    , Oct 18, 2006
    #13
  14. writes:
    [...]
    > Keep in mind that "static" function declarations are usually basically
    > equivalent to what is intended by C99's "inline". For serious
    > compilers, there should be no effective difference between the two
    > (inline further asserts that taking the address of the function is
    > illegal, however, a static function whose address *isn't* taken (which
    > it can always determine because it *is* static) becomes equivalent in
    > functional status.)


    I believe it's perfectly legal to take the address of an inline
    function. Can you cite something in the standard that says otherwise?
    In particular, the function call operator expects a
    pointer-to-function, so just calling a function implicitly takes its
    address.

    (The standard *could* have said that taking the address of an inline
    function other than in a direct call is illegal, but it doesn't.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Oct 19, 2006
    #14
  15. wrote:
    > ...
    > inline further asserts that taking the address of the function is
    > illegal
    > ...


    That's incorrect. There's absolutely nothing illegal in taking the address of an
    inline function.

    --
    Best regards,
    Andrey Tarasevich
    Andrey Tarasevich, Oct 19, 2006
    #15
  16. Robert Seacord

    Ian Collins Guest

    Frederick Gotham wrote:
    > Robert Seacord posted:
    >
    >
    >>When writing C99 code is a reasonable recommendation to use inline
    >>functions instead of macros?

    >
    >
    >
    > Not in general, no, for three reasons:
    >
    > (1) C90 doesn't support inline.


    The OP asked about C99.

    > (2) Even if the compiler _does_ support inline, the code is guaranteed to
    > be inlined.
    > (3) It doesn't yield a compile-time constant.
    >

    ?

    --
    Ian Collins.
    Ian Collins, Oct 19, 2006
    #16
  17. Ian Collins said:

    > Frederick Gotham wrote:
    >> Robert Seacord posted:
    >>
    >>>When writing C99 code is a reasonable recommendation to use inline
    >>>functions instead of macros?

    >>
    >> Not in general, no, for three reasons:
    >>
    >> (1) C90 doesn't support inline.

    >
    > The OP asked about C99.


    Nevertheless, it's a reasonable point. When writing C99 code, it is for the
    time being (and, the way, we're going, for the foreseeable future too)
    reasonable to keep the code portable to C90, unless one is prepared to
    forego the advantages thereof.

    >> (2) Even if the compiler _does_ support inline, the code is guaranteed to
    >> be inlined.
    >> (3) It doesn't yield a compile-time constant.
    >>

    > ?


    I'm not sure what he means by that, either.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
    Richard Heathfield, Oct 19, 2006
    #17
  18. Andrew Poelstra said:

    > On Wed, 2006-10-18 at 21:16 +0000, Frederick Gotham wrote:
    >> Robert Seacord posted:
    >>
    >> > When writing C99 code is a reasonable recommendation to use inline
    >> > functions instead of macros?

    >> Not in general, no, for three reasons:
    >>
    >> (1) C90 doesn't support inline.
    >> (2) Even if the compiler _does_ support inline, the code is guaranteed to
    >> be inlined.

    >
    > You meant /not/ guaranteed to be inline. According to C99, that is.


    I am fairly sure he meant something like "[the macro version of] the code is
    *guaranteed* to be inlined".

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
    Richard Heathfield, Oct 19, 2006
    #18
  19. Robert Seacord

    Ian Collins Guest

    Richard Heathfield wrote:
    > Ian Collins said:
    >
    >
    >>Frederick Gotham wrote:
    >>
    >>>Robert Seacord posted:
    >>>
    >>>
    >>>>When writing C99 code is a reasonable recommendation to use inline
    >>>>functions instead of macros?
    >>>
    >>>Not in general, no, for three reasons:
    >>>
    >>>(1) C90 doesn't support inline.

    >>
    >>The OP asked about C99.

    >
    >
    > Nevertheless, it's a reasonable point. When writing C99 code, it is for the
    > time being (and, the way, we're going, for the foreseeable future too)
    > reasonable to keep the code portable to C90, unless one is prepared to
    > forego the advantages thereof.
    >

    True, which brings us back to the old dilemma of pragmatism or
    portability. I think every recent (last 10 years) C compiler I've used
    either supports inline as an extension, or inlines as an optimisation,
    or both.


    --
    Ian Collins.
    Ian Collins, Oct 19, 2006
    #19
  20. Ian Collins said:

    > Richard Heathfield wrote:


    [...]

    >> When writing C99 code, it is for
    >> the time being (and, the way, we're going, for the foreseeable future
    >> too) reasonable to keep the code portable to C90, unless one is prepared
    >> to forego the advantages thereof.
    >>

    > True, which brings us back to the old dilemma of pragmatism or
    > portability.


    For me, portability is part of pragmatism.

    And so, of course, is non-portability.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
    Richard Heathfield, Oct 19, 2006
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    3
    Views:
    456
  2. Daniel Vallstrom
    Replies:
    2
    Views:
    1,867
    Kevin Bracey
    Nov 21, 2003
  3. Replies:
    80
    Views:
    2,414
    Stephen J. Bevan
    Nov 7, 2003
  4. Replies:
    1
    Views:
    437
    Marco Antoniotti
    Oct 7, 2003
  5. Rahul
    Replies:
    3
    Views:
    452
    James Kanze
    Feb 28, 2008
Loading...

Share This Page