inline functions vs. macros

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Robert Seacord

    #1

    inline functions vs. macros


    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
  • Ben Pfaff

    #2
    Re: inline functions vs. macros

    Robert Seacord <rcs@sei.cmu.ed uwrites:
    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

    Comment

    • Darko

      #3
      Re: inline functions vs. 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.

      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

      Comment

      • Andrey Tarasevich

        #4
        Re: inline functions vs. macros

        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(dou ble, d)
        DEFINE_CUBE(int , i)
        DEFINE_CUBE(uns igned, ui)

        --
        Best regards,
        Andrey Tarasevich

        Comment

        • Richard Heathfield

          #5
          Re: inline functions vs. macros

          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

          email: rjh at above domain (but drop the www, obviously)

          Comment

          • Ancient_Hacker

            #6
            Re: inline functions vs. macros


            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.

            Comment

            • John Bode

              #7
              Re: inline functions vs. macros


              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.

              Comment

              • Ian Collins

                #8
                Re: inline functions vs. macros

                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.

                Comment

                • Frederick Gotham

                  #9
                  Re: inline functions vs. macros

                  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

                  Comment

                  • Christopher Benson-Manica

                    #10
                    Re: inline functions vs. macros

                    Frederick Gotham <fgothamNO@spam .comwrote:
                    (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)gma il.com | don't, I need to know. Flames welcome.

                    Comment

                    • Andrew Poelstra

                      #11
                      Re: inline functions vs. macros

                      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/>

                      Comment

                      • Pedro Graca

                        #12
                        Re: inline functions vs. macros

                        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

                        Comment

                        • websnarf@gmail.com

                          #13
                          Re: inline functions vs. macros

                          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(ta ble,i);
                          hf_idxNext(tabl e,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
                          Pobox has been discontinued as a separate service, and all existing customers moved to the Fastmail platform.



                          Comment

                          • Keith Thompson

                            #14
                            Re: inline functions vs. macros

                            websnarf@gmail. com 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_Keit h) kst-u@mib.org <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.

                            Comment

                            • Andrey Tarasevich

                              #15
                              Re: inline functions vs. macros

                              websnarf@gmail. com 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

                              Comment

                              Working...