standard functions as macros

Discussion in 'C Programming' started by vippstar@gmail.com, Jan 4, 2008.

  1. Guest

    This question might be OT I apologise if it is.

    All functions are allowed to be macros.
    In a hypothetical implementation a tolower might be written as:

    #define tolower(x) \
    (x) == 'A' ? 'a' : \
    (x) == 'B' ? 'b' : \
    /* etc */
    (x) == 'Z' ? 'z' : (x)

    Ofcourse this has other problems (example if you pass i++ to it) but
    we don't care about that now.

    What I care about is 2 things:

    o How does the compiler warn about incorrect arguments passed/etc?
    Normally the preprocessor will change the source code, for example:

    int add_one(int x);
    #define add_one(x) ((x)+1)
    /* ... */
    char foo[2];
    char * p = foo;
    char * s = add_one(p); /* at this point, the compiler won't see a
    'call to add_one since it would be replaced by the pp. */

    o How does the macro work if I don't pass any arguments?
    example:
    int foo(unsigned x);
    #define foo(x) (~(x))
    /* ... */
    int (*ptr)(void) = foo; /* how does that work? */

    My tolower() macro example would not work in both cases.


    thank you for your answers
     
    , Jan 4, 2008
    #1
    1. Advertising

  2. Guest

    On Jan 4, 2:02 pm, wrote:
    > o How does the macro work if I don't pass any arguments?
    > example:
    > int foo(unsigned x);
    > #define foo(x) (~(x))
    > /* ... */
    > int (*ptr)(void) = foo; /* how does that work? */

    What I ment here is int (*ptr)(int), I changed the function while I
    was posting but I forgot to change ptr.
     
    , Jan 4, 2008
    #2
    1. Advertising

  3. Richard Bos Guest

    wrote:

    > All functions are allowed to be macros.


    With caveats.

    > In a hypothetical implementation a tolower might be written as:
    >
    > #define tolower(x) \
    > (x) == 'A' ? 'a' : \
    > (x) == 'B' ? 'b' : \
    > /* etc */
    > (x) == 'Z' ? 'z' : (x)
    >
    > Ofcourse this has other problems (example if you pass i++ to it) but
    > we don't care about that now.
    >
    > What I care about is 2 things:
    >
    > o How does the compiler warn about incorrect arguments passed/etc?


    Depends on the implementation

    > Normally the preprocessor will change the source code, for example:
    >
    > int add_one(int x);
    > #define add_one(x) ((x)+1)
    > /* ... */
    > char foo[2];
    > char * p = foo;
    > char * s = add_one(p); /* at this point, the compiler won't see a
    > 'call to add_one since it would be replaced by the pp. */


    Some implementations will remember this, and use the proper name to
    complain. Some will not.

    > o How does the macro work if I don't pass any arguments?
    > example:
    > int foo(unsigned x);
    > #define foo(x) (~(x))
    > /* ... */
    > int (*ptr)(void) = foo; /* how does that work? */


    This, at least, works: the macro foo is not the same macro as foo().

    Richard
     
    Richard Bos, Jan 4, 2008
    #3
  4. Guest

    On Jan 4, 2:18 pm, (Richard Bos) wrote:
    > This, at least, works: the macro foo is not the same macro as foo().

    Ah, this is what I had in mind too, therefore the implementation must
    provide a function pointer 'x' that does the equivalent of the macro
    'x()'.
    Thanks for clearing this Richard.
     
    , Jan 4, 2008
    #4
  5. James Kuyper Guest

    wrote:
    > On Jan 4, 2:18 pm, (Richard Bos) wrote:
    >> This, at least, works: the macro foo is not the same macro as foo().

    > Ah, this is what I had in mind too, therefore the implementation must
    > provide a function pointer 'x' that does the equivalent of the macro
    > 'x()'.


    This is explicitly required by the standard for any standard library
    function implemented as a function-like macro. Note, however, that some
    standard library features are explicitly described as function-like
    macros, such as in <stdarg.h>. In those cases, there is no underlying
    function that can be called.
     
    James Kuyper, Jan 4, 2008
    #5
  6. Army1987 Guest

    vippstar wrote:

    > This question might be OT I apologise if it is.
    >
    > All functions are allowed to be macros.
    > In a hypothetical implementation a tolower might be written as:
    >
    > #define tolower(x) \
    > (x) == 'A' ? 'a' : \
    > (x) == 'B' ? 'b' : \
    > /* etc */
    > (x) == 'Z' ? 'z' : (x)
    >
    > Ofcourse this has other problems (example if you pass i++ to it) but
    > we don't care about that now.

    No. Macro implementations are required to evaluate each argument exactly
    once, and to have enough parentheses.
    > What I care about is 2 things:
    >
    > o How does the compiler warn about incorrect arguments passed/etc?
    > Normally the preprocessor will change the source code, for example:
    >
    > int add_one(int x);
    > #define add_one(x) ((x)+1)
    > /* ... */
    > char foo[2];
    > char * p = foo;
    > char * s = add_one(p); /* at this point, the compiler won't see a
    > 'call to add_one since it would be replaced by the pp. */


    So what? Of course, the macro implementation of a standard library
    function must have the right type, so it'd be ((int)(x)+1). So the
    compiler *can* see that there's something wrong.
    > o How does the macro work if I don't pass any arguments?
    > example:
    > int foo(unsigned x);
    > #define foo(x) (~(x))
    > /* ... */
    > int (*ptr)(void) = foo; /* how does that work? */

    The identifier foo gets replaced by the preprocessor only if immediately
    followed by a ( token. ("Immediately" here includes the case in which
    there is whitespace/comments between them.)

    --
    Army1987 (Replace "NOSPAM" with "email")
     
    Army1987, Jan 4, 2008
    #6
  7. pete Guest

    Army1987 wrote:
    >
    > vippstar wrote:
    >
    > > This question might be OT I apologise if it is.
    > >
    > > All functions are allowed to be macros.
    > > In a hypothetical implementation a tolower might be written as:
    > >
    > > #define tolower(x) \
    > > (x) == 'A' ? 'a' : \
    > > (x) == 'B' ? 'b' : \
    > > /* etc */
    > > (x) == 'Z' ? 'z' : (x)
    > >
    > > Ofcourse this has other problems (example if you pass i++ to it) but
    > > we don't care about that now.

    > No. Macro implementations are required to
    > evaluate each argument exactly once,
    > and to have enough parentheses.


    putc and getc macros
    may evaluate their stream argument more than once.

    --
    pete
     
    pete, Jan 4, 2008
    #7
  8. On Fri, 04 Jan 2008 17:30:07 -0500, pete wrote:
    > Army1987 wrote:
    >> vippstar wrote:
    >> > #define tolower(x) \
    >> > (x) == 'A' ? 'a' : \
    >> > (x) == 'B' ? 'b' : \
    >> > /* etc */
    >> > (x) == 'Z' ? 'z' : (x)
    >> >
    >> > Ofcourse this has other problems (example if you pass i++ to it) but
    >> > we don't care about that now.

    >> No. Macro implementations are required to evaluate each argument
    >> exactly once,
    >> and to have enough parentheses.

    >
    > putc and getc macros
    > may evaluate their stream argument more than once.


    assert is a macro and may not evaluate its argument at all, depending on
    NDEBUG.

    But that's because special permissions or requirements are explicitly
    stated. Since no such special permissions or requirements apply to
    tolower, the general requirements apply, which do state each argument
    must be evaluated exactly once.
     
    Harald van Dijk, Jan 4, 2008
    #8
    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:
    80
    Views:
    2,514
    Stephen J. Bevan
    Nov 7, 2003
  2. Replies:
    1
    Views:
    489
    Marco Antoniotti
    Oct 7, 2003
  3. Replies:
    5
    Views:
    513
  4. Michael T. Babcock

    Re: Explanation of macros; Haskell macros

    Michael T. Babcock, Nov 3, 2003, in forum: Python
    Replies:
    0
    Views:
    540
    Michael T. Babcock
    Nov 3, 2003
  5. Andrew Arro

    macros-loop? calling macros X times?

    Andrew Arro, Jul 23, 2004, in forum: C Programming
    Replies:
    2
    Views:
    516
    S.Tobias
    Jul 24, 2004
Loading...

Share This Page