More Macro questions

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

    More Macro questions

    I have asked a few questions about Macros...and think what I have been
    missing ...and which all who have replied clearly understand...is that
    this is a Pre-processor action.
    Hopefully the above is true.
    So, could someone look at this code, and help me understand why I get
    this error.


    #include <stdio.h>

    #define get_char() getc(stdin)
    #define put_char(x) putc(x, stdout)

    int main (int argc, const char * argv[]) {
    int c;
    while ( (c = get_char) != EOF) /* error: 'get_char' undeclared
    (first use in this function) */
    put_char(c);
    return 0;
    }

    I **thought** what would happen is that get_char would be replaced by
    "getc(stdin )".

    Thanks
  • Richard Heathfield

    #2
    Re: More Macro questions

    mdh said:

    <snip>
    #include <stdio.h>
    >
    #define get_char() getc(stdin)
    #define put_char(x) putc(x, stdout)
    >
    int main (int argc, const char * argv[]) {
    int c;
    while ( (c = get_char) != EOF) /* error: 'get_char' undeclared
    (first use in this function) */
    put_char(c);
    return 0;
    }
    >
    I **thought** what would happen is that get_char would be replaced by
    "getc(stdin )".
    Then you'll want #define get_char getc(stdin)

    Please bear in mind, though, that this is a poor use of a macro.

    The above program would be better written as follows:

    #include <stdio.h>

    int main(void)
    {
    int c;
    while((c = getchar()) != EOF)
    putchar(c);
    return 0;
    }

    Avoid macros except on occasions where their advantages outweigh their
    disadvantages, which is pretty rare.

    --
    Richard Heathfield <http://www.cpax.org.uk >
    Email: -http://www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999

    Comment

    • mdh

      #3
      Re: More Macro questions

      On Sep 30, 7:21 am, Richard Heathfield <r...@see.sig.i nvalidwrote:
      mdh said:
      >
      <snip>
      >
      >
      #define get_char() getc(stdin)
      #define put_char(x) putc(x, stdout)
      >
      int main (int argc, const char * argv[]) {
          int c;
          while ( (c = get_char) != EOF) /* error: 'get_char' undeclared
      (first use in this function) */
              put_char(c);
          return 0;
      }
      >
      I **thought** what would happen is that get_char would be replaced by
      "getc(stdin )".
      >
      Then you'll want #define get_char getc(stdin)

      Richard...you lost me. I thought that is what the define statement
      did?



      >
      Please bear in mind, though, that this is a poor use of a macro.

      Richard...I have no doubt that this is true. The only reason I did
      this was to see **how** they work. Perhaps you could explain why it is
      a poor use and when you tend to use it ( rarely...as noted below!) ,
      as a good example.



      >
      The above program would be better written as follows:
      >
      #include <stdio.h>
      >
      int main(void)
      {
        int c;
        while((c = getchar()) != EOF)
          putchar(c);
        return 0;
      >
      }




      >
      Avoid macros except on occasions where their advantages outweigh their
      disadvantages, which is pretty rare.

      Comment

      • Joachim Schmitz

        #4
        Re: More Macro questions

        mdh wrote:
        On Sep 30, 7:21 am, Richard Heathfield <r...@see.sig.i nvalidwrote:
        >mdh said:
        >>
        ><snip>
        >>
        >>>
        >>
        >>#define get_char() getc(stdin)
        >>#define put_char(x) putc(x, stdout)
        >>
        >>int main (int argc, const char * argv[]) {
        >>int c;
        >>while ( (c = get_char) != EOF) /* error: 'get_char' undeclared
        >>(first use in this function) */
        >>put_char(c) ;
        >>return 0;
        >>}
        >>
        >>I **thought** what would happen is that get_char would be replaced
        >>by "getc(stdin )".
        >>
        >Then you'll want #define get_char getc(stdin)
        >
        >
        Richard...you lost me. I thought that is what the define statement
        did?
        with RH's
        #define get_char getc(stdin)

        you define a plain macro vs. your
        #define get_char() getc(stdin)

        which defines a function like macro.
        But in your code you don't use it as a function like macro:
        (c = get_char)

        So either use
        #define get_char getc(stdin)

        or
        (c = get_char())

        Bye, Jojo


        Comment

        • mdh

          #5
          Re: More Macro questions

          On Sep 30, 7:35 am, "Joachim Schmitz" <nospam.j...@sc hmitz-digital.de>
          wrote:
          >
          So either use
          #define get_char getc(stdin)
          >
          or
          (c = get_char())
          >
          Bye, Jojo
          oops...thanks.

          Comment

          • Nick Keighley

            #6
            Re: More Macro questions

            On 30 Sep, 15:26, mdh <m...@comcast.n etwrote:
            On Sep 30, 7:21 am, Richard Heathfield <r...@see.sig.i nvalidwrote:
            mdh said:
            #define get_char() getc(stdin)
            #define put_char(x) putc(x, stdout)
            >
            int main (int argc, const char * argv[]) {
                int c;
                while ( (c = get_char) != EOF) /* error: 'get_char' undeclared
            (first use in this function) */
                    put_char(c);
                return 0;
            }
            >
            I **thought** what would happen is that get_char would be replaced by
            "getc(stdin )".
            >
            Then you'll want #define get_char getc(stdin)
            >
            Richard...you lost me. I thought that is what the define statement
            did?
            >
            Please bear in mind, though, that this is a poor use of a macro.
            >
            Richard...I have no doubt that this is true. The only reason I did
            this was to see **how** they work. Perhaps you could explain why it is
            a poor use and when you tend to use it ( rarely...as noted below!) ,
            as a good example.
            <snip>

            macro substitution is carroed out by a macro processor.
            The so-called "pre-processor"[1]. The pp is pretty ignorant
            of C. It simply substitutes text. This means you have missed
            important argument checking that the compiler proper can carry out.
            You also get that multiple argument evaluation stuff.

            #define SQUARE(A) A * A

            looks ok? What does these do?

            SQUARE(a++);
            SQUARE(a + b);

            Another nasty practice is people who decide C syntax can
            be improved with a few macros

            #define procedure void
            #define integer int
            #define begin {
            #define end }
            #define writeln(n) printf ("%d\n", n)


            procedure p (integer i)
            begin
            writeln (i);
            end


            trust me, no one will thank you for this


            [1] at least conceptually. A clever compiler writer may avoid having
            a
            separate pp stage provided he gets the same answer "as-if" he'd used
            a pp. The so-called "as-if" rule.


            --
            Nick Keighley

            "I have always wished that my computer would be as easy to use as my
            telephone. My wish has come true. I no longer know how to use my
            telephone."
            - Bjarne Stroustrup

            Comment

            • mdh

              #7
              Re: More Macro questions

              On Sep 30, 8:11 am, Nick Keighley <nick_keighley_ nos...@hotmail. com>
              wrote:
              On 30 Sep, 15:26, mdh <m...@comcast.n etwrote:
              >
              <snip>
              >
              macro substitution is carroed out by a macro processor.
              The so-called "pre-processor"[1]. The pp is pretty ignorant
              of C. It simply substitutes text. This means you have missed
              important argument checking that the compiler proper can carry out.
              You also get that multiple argument evaluation stuff.
              >

              thanks Nick. I find it instructive to understand why something is poor
              as well as good practice. One of the **disadvantages ** ( if there are
              any) of K&R is that they do not teach you **bad** C, so this is left
              to you ( as in me) to discover. Fortunately, the clc soon disavows one
              of one's bad habits!!! :-)

              Comment

              • Keith Thompson

                #8
                Re: More Macro questions

                mdh <mdeh@comcast.n etwrites:
                I have asked a few questions about Macros...and think what I have been
                missing ...and which all who have replied clearly understand...is that
                this is a Pre-processor action.
                Hopefully the above is true.
                So, could someone look at this code, and help me understand why I get
                this error.
                >
                >
                #include <stdio.h>
                >
                #define get_char() getc(stdin)
                #define put_char(x) putc(x, stdout)
                >
                int main (int argc, const char * argv[]) {
                int c;
                while ( (c = get_char) != EOF) /* error: 'get_char' undeclared
                (first use in this function) */
                put_char(c);
                return 0;
                }
                >
                I **thought** what would happen is that get_char would be replaced by
                "getc(stdin )".
                There are two different kinds of macros, "function-like" and
                "object-like".

                A function-like macro, like your get_char and put_char, takes zero or
                more arguments. In the definition, the opening '(' immediately
                follows the macro name, without even whitespace between them. An
                invocation looks very much like a function call. A reference to the
                name of a function-like macro that's not followed by a '(' (possibly
                with whitespace in between) isn't recognized. (Possibly making this
                an error would have been better.)

                And that's the problem in your program; you need to write "get_char() "
                rather than "get_char".

                An object-like macro takes no arguments; it just expands to whatever
                it's defined as. EOF and NULL are examples.

                --
                Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                Nokia
                "We must do something. This is something. Therefore, we must do this."
                -- Antony Jay and Jonathan Lynn, "Yes Minister"

                Comment

                • mdh

                  #9
                  Re: More Macro questions

                  On Sep 30, 9:46 am, Keith Thompson <ks...@mib.orgw rote:
                  mdh <m...@comcast.n etwrites:

                  int main (int argc, const char * argv[]) {
                      int c;
                      while ( (c = get_char) != EOF) /* error: 'get_char' undeclared
                  (first use in this function) */
                          put_char(c);
                      return 0;
                  }
                  >
                  .
                  >
                  A function-like macro, like your get_char and put_char, takes zero or
                  more arguments.  In the definition, the opening '(' immediately
                  follows the macro name, without even whitespace between them.  An
                  invocation looks very much like a function call.  A reference to the
                  name of a function-like macro that's not followed by a '(' (possibly
                  with whitespace in between) isn't recognized.  (Possibly making this
                  an error would have been better.)
                  >
                  And that's the problem in your program; you need to write "get_char() "
                  rather than "get_char".
                  >
                  An object-like macro takes no arguments; it just expands to whatever
                  it's defined as.  EOF and NULL are examples.
                  >
                  Thanks Keith.
                  Just out of curiosity, when would you choose to use a function-like
                  Macro? I think we spoke before about that being the way that C
                  implements va_list. But have not seen good examples of user-written
                  function-like Macros.
                  Being one who follows good advice ( as far as I can) I take Richard
                  Heathfield's admonition seriously. "Avoid macros except on occasions
                  where their advantages outweigh their disadvantages, which is pretty
                  rare", but I am still curious.



                  Comment

                  • Keith Thompson

                    #10
                    Re: More Macro questions

                    mdh <mdeh@comcast.n etwrites:
                    [...]
                    Just out of curiosity, when would you choose to use a function-like
                    Macro? I think we spoke before about that being the way that C
                    implements va_list. But have not seen good examples of user-written
                    function-like Macros.
                    va_list itself isn't (necessarily) a macro at all, but va_arg,
                    va_copy, va_end, and va_start are all function-like macros.

                    Use a function-like macro when you want something that looks and
                    (mostly) behaves like a callable function, but when an actual function
                    won't do the job. In the old days, the most common reason was
                    performance, but modern compilers are generally able to inline small
                    functions. A function-like macro can be used when you want to pass
                    something other than an expression value.

                    The standard offsetof macro is a good example; its second argument is
                    a member name, something that you couldn't pass to a function.

                    And any standard function may additionally be implemented as a macro,
                    usually for performance reasons.

                    Here's my favorite example of a horrid mis-use of the macro facility,
                    a demonstration that Douglas Adams was right in The Hitchhiker's Guide
                    to the Galaxy:

                    #include <stdio.h>

                    #define SIX 1+5
                    #define NINE 8+1

                    int main(void)
                    {
                    printf("%d * %d = %d\n", SIX, NINE, SIX * NINE);
                    return 0;
                    }
                    Being one who follows good advice ( as far as I can) I take Richard
                    Heathfield's admonition seriously. "Avoid macros except on occasions
                    where their advantages outweigh their disadvantages, which is pretty
                    rare", but I am still curious.
                    Emininently reasonable on both counts.

                    --
                    Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                    Nokia
                    "We must do something. This is something. Therefore, we must do this."
                    -- Antony Jay and Jonathan Lynn, "Yes Minister"

                    Comment

                    • mdh

                      #11
                      Re: More Macro questions

                      On Sep 30, 1:06 pm, Keith Thompson <ks...@mib.orgw rote:
                      mdh <m...@comcast.n etwrites:
                      >
                      [...]
                      >
                      Just out of curiosity, when would you choose to use a function-like
                      Macro?  I think we spoke before about that being  the way that C
                      implements  va_list. But have not seen good examples of user-written
                      function-like Macros.
                      >
                      va_list itself isn't (necessarily) a macro at all, but va_arg,
                      va_copy, va_end, and va_start are all function-like macros.
                      >
                      Use a function-like macro when you want something that looks and
                      (mostly) behaves like a callable function, but when an actual function
                      won't do the job.  In the old days, the most common reason was
                      performance, but modern compilers are generally able to inline small
                      functions.  A function-like macro can be used when you want to pass
                      something other than an expression value.
                      >
                      The standard offsetof macro is a good example; its second argument is
                      a member name, something that you couldn't pass to a function.
                      >
                      And any standard function may additionally be implemented as a macro,
                      usually for performance reasons.
                      >
                      Here's my favorite example of a horrid mis-use of the macro facility,
                      a demonstration that Douglas Adams was right in The Hitchhiker's Guide
                      to the Galaxy:
                      >
                      #include <stdio.h>
                      >
                      #define SIX 1+5
                      #define NINE 8+1
                      >
                      int main(void)
                      {
                          printf("%d * %d = %d\n", SIX, NINE, SIX * NINE);
                          return 0;
                      >
                      }
                      Being one who follows good advice ( as far as I can) I take Richard
                      Heathfield's admonition seriously. "Avoid macros except on occasions
                      where their advantages outweigh their disadvantages, which is pretty
                      rare", but I am still curious.
                      >
                      Emininently reasonable on both counts.
                      >
                      --
                      Keith Thompson (The_Other_Keit h) ks...@mib.org  <http://www.ghoti.net/~kst>
                      Nokia
                      "We must do something.  This is something.  Therefore, we must do this."
                          -- Antony Jay and Jonathan Lynn, "Yes Minister"
                      Thank you Richard for that explanation.

                      Comment

                      • mdh

                        #12
                        Re: More Macro questions

                        On Sep 30, 1:06 pm, Keith Thompson <ks...@mib.orgw rote:
                        mdh <m...@comcast.n etwrites:
                        >
                        [...]
                        >
                        Just out of curiosity, when would you choose to use a function-like
                        Macro?  I think we spoke before about that being  the way that C
                        implements  va_list. But have not seen good examples of user-written
                        function-like Macros.
                        >
                        va_list itself isn't (necessarily) a macro at all, but va_arg,
                        va_copy, va_end, and va_start are all function-like macros.
                        >
                        Use a function-like macro when you want something that looks and
                        (mostly) behaves like a callable function, but when an actual function
                        won't do the job.  In the old days, the most common reason was
                        performance, but modern compilers are generally able to inline small
                        functions.  A function-like macro can be used when you want to pass
                        something other than an expression value.
                        >
                        The standard offsetof macro is a good example; its second argument is
                        a member name, something that you couldn't pass to a function.
                        >
                        And any standard function may additionally be implemented as a macro,
                        usually for performance reasons.
                        >
                        Here's my favorite example of a horrid mis-use of the macro facility,
                        a demonstration that Douglas Adams was right in The Hitchhiker's Guide
                        to the Galaxy:
                        >
                        #include <stdio.h>
                        >
                        #define SIX 1+5
                        #define NINE 8+1
                        >
                        int main(void)
                        {
                            printf("%d * %d = %d\n", SIX, NINE, SIX * NINE);
                            return 0;
                        >
                        }
                        Being one who follows good advice ( as far as I can) I take Richard
                        Heathfield's admonition seriously. "Avoid macros except on occasions
                        where their advantages outweigh their disadvantages, which is pretty
                        rare", but I am still curious.
                        >
                        Emininently reasonable on both counts.
                        >
                        --
                        Keith Thompson (The_Other_Keit h) ks...@mib.org  <http://www.ghoti.net/~kst>
                        Nokia
                        "We must do something.  This is something.  Therefore, we must do this."
                            -- Antony Jay and Jonathan Lynn, "Yes Minister"
                        Red in Face!!!

                        Thanks Keith!

                        Comment

                        • Keith Thompson

                          #13
                          Re: More Macro questions

                          mdh <mdeh@comcast.n etwrites:
                          On Sep 30, 1:06 pm, Keith Thompson <ks...@mib.orgw rote:
                          >mdh <m...@comcast.n etwrites:
                          [...]
                          Being one who follows good advice ( as far as I can) I take Richard
                          Heathfield's admonition seriously. "Avoid macros except on occasions
                          where their advantages outweigh their disadvantages, which is pretty
                          rare", but I am still curious.
                          >>
                          >Emininently reasonable on both counts.
                          >>
                          >--
                          >Keith Thompson (The_Other_Keit h) ks...@mib.org  <http://www.ghoti.net/~kst>
                          >Nokia
                          >"We must do something.  This is something.  Therefore, we must do this."
                          >    -- Antony Jay and Jonathan Lynn, "Yes Minister"
                          >
                          Red in Face!!!
                          >
                          Thanks Keith!
                          You're welcome.

                          You could un-redden your face even more by not quoting the entire
                          article (particularly the signature) just for a "thanks". Quote just
                          enough so your followup makes sense on its own.

                          --
                          Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                          Nokia
                          "We must do something. This is something. Therefore, we must do this."
                          -- Antony Jay and Jonathan Lynn, "Yes Minister"

                          Comment

                          • Chris M. Thomasson

                            #14
                            Re: More Macro questions

                            "mdh" <mdeh@comcast.n etwrote in message
                            news:79225757-ee20-4585-874d-59c0eb596f9a@z6 6g2000hsc.googl egroups.com...
                            On Sep 30, 9:46 am, Keith Thompson <ks...@mib.orgw rote:
                            mdh <m...@comcast.n etwrites:
                            >
                            int main (int argc, const char * argv[]) {
                            int c;
                            while ( (c = get_char) != EOF) /* error: 'get_char' undeclared
                            (first use in this function) */
                            put_char(c);
                            return 0;
                            }
                            .
                            A function-like macro, like your get_char and put_char, takes zero or
                            more arguments. In the definition, the opening '(' immediately
                            follows the macro name, without even whitespace between them. An
                            invocation looks very much like a function call. A reference to the
                            name of a function-like macro that's not followed by a '(' (possibly
                            with whitespace in between) isn't recognized. (Possibly making this
                            an error would have been better.)

                            And that's the problem in your program; you need to write "get_char() "
                            rather than "get_char".

                            An object-like macro takes no arguments; it just expands to whatever
                            it's defined as. EOF and NULL are examples.
                            Thanks Keith.
                            Just out of curiosity, when would you choose to use a function-like
                            Macro?
                            [...]

                            You can use function macro names as function pointers for other macros...
                            Think along lines of something like:
                            _______________ _______________ _______________ _______________ _____
                            #include <stdio.h>

                            #define QUOTE_IMPL(mp_t ext)#mp_text
                            #define QUOTE(mp_text) \
                            QUOTE_IMPL(mp_t ext)


                            #define PLACE(mp_text)m p_text


                            #define MY_MACRO_FUNC_1 (mp_text) \
                            PLACE(Hello from my macro func 1 mp_text)

                            #define MY_MACRO_FUNC_2 (mp_text) \
                            PLACE(Hello from my macro func 2 mp_text)

                            #define INVOKE_MACRO_FU NC(mp_fpname, mp_params) \
                            mp_fpname mp_params


                            int main(void) {
                            puts(QUOTE(INVO KE_MACRO_FUNC(M Y_MACRO_FUNC_1, (invoker.))));
                            puts(QUOTE(INVO KE_MACRO_FUNC(M Y_MACRO_FUNC_2, (invoker.))));
                            return 0;
                            }

                            _______________ _______________ _______________ _______________ _____




                            Here is real world use of macro function pointer:



                            Look at the section under `Array Init Support' and study the PLACE macros.
                            Then look at the `Global Lock Table' and study the way I initialize the
                            arrays.




                            Also read here:





                            Macro function pointers using names of func-like macros as the actual
                            func-pointer has advantages, such as automating static initialization.

                            Comment

                            • Chris M. Thomasson

                              #15
                              Re: More Macro questions

                              "Keith Thompson" <kst-u@mib.orgwrote in message
                              news:lnr671wpha .fsf@nuthaus.mi b.org...
                              mdh <mdeh@comcast.n etwrites:
                              >I have asked a few questions about Macros...and think what I have been
                              >missing ...and which all who have replied clearly understand...is that
                              >this is a Pre-processor action.
                              >Hopefully the above is true.
                              >So, could someone look at this code, and help me understand why I get
                              >this error.
                              >>
                              >>
                              >#include <stdio.h>
                              >>
                              >#define get_char() getc(stdin)
                              >#define put_char(x) putc(x, stdout)
                              >>
                              >int main (int argc, const char * argv[]) {
                              > int c;
                              > while ( (c = get_char) != EOF) /* error: 'get_char' undeclared
                              >(first use in this function) */
                              > put_char(c);
                              > return 0;
                              >}
                              >>
                              >I **thought** what would happen is that get_char would be replaced by
                              >"getc(stdin) ".
                              >
                              There are two different kinds of macros, "function-like" and
                              "object-like".
                              >
                              A function-like macro, like your get_char and put_char, takes zero or
                              more arguments. In the definition, the opening '(' immediately
                              follows the macro name, without even whitespace between them. An
                              invocation looks very much like a function call.
                              I am a little confused about the whitespace comment... Are you saying the
                              following is actually invalid:


                              #define PLACE(token)tok en

                              PLACE ((1+1)==2);


                              If so, then I really need to correct my awnser to mdh found here:




                              The 'INVOKE_MACRO_F UNC' macro expansion will insert a whitespace between the
                              macro "function pointer" name and its argument list... Here is simple
                              attempt to omit whitespace:
                              _______________ _______________ _______________ _______________ ___
                              #include <stdio.h>
                              #include <assert.h>

                              #define QUOTE_IMPL(mp_t ext)#mp_text
                              #define QUOTE(mp_text) \
                              QUOTE_IMPL(mp_t ext)


                              #define PLACE(mp_text)m p_text


                              #define MY_MACRO_FUNC_1 (mp_text) \
                              PLACE(Hello from my macro func 1 mp_text)

                              #define MY_MACRO_FUNC_2 (mp_text) \
                              PLACE(Hello from my macro func 2 mp_text)

                              #define INVOKE_MACRO_FU NC(mp_fpname, mp_params) \
                              PLACE(mp_fpname )mp_params


                              int main(void) {
                              puts(QUOTE(INVO KE_MACRO_FUNC(M Y_MACRO_FUNC_1, (invoker.))));
                              puts(QUOTE(INVO KE_MACRO_FUNC(M Y_MACRO_FUNC_2, (invoker.))));
                              return 0;
                              }

                              _______________ _______________ _______________ _______________ ___


                              Now I use PLACE macro to output the token, then the function params
                              immediately follow it. The expansion should not insert any whitespaces in
                              between them; well, at least I think it should not! ;^/



                              Anyway, if I misunderstood you, well, then I am sorry for _wasting_ your
                              time!

                              ;^(


                              [...]

                              Comment

                              Working...