Macro function syntax

Discussion in 'C Programming' started by Ann O'Nymous, Jul 28, 2010.

  1. Ann O'Nymous

    Ann O'Nymous Guest

    I have a macro function that's like the following:

    int function2(int*,int,int,int);

    #define xyz(a,b,c) {\
    int x[100],i; \
    for(i=0;i<c;i++) x = something(a,b,c); \
    function2(x,a,b,c); \
    }

    where "something" is a mathematical expression of a,b and c, and
    "function2" is a function returning int.

    Calls like:

    xyz(1,2,3);

    work fine, other than the return value of "function2" gets thrown away.

    Now, if I want to do this:

    int jkl;
    ....
    jkl = xyz(1,2,3);
    ....

    where "jkl" is to get that value returned by "function2", how do I do
    it? I'm having trouble with the syntax.

    I want things to expand where:

    jkl = xyz(p,q,r);

    expands equivalently to:
    {
    int x[100],i;
    for(i=0;i<r;i++) x = something(p,q,r);
    jkl = function2(x,p,q,r);
    }
     
    Ann O'Nymous, Jul 28, 2010
    #1
    1. Advertising

  2. Ann O'Nymous

    Ann O'Nymous Guest

    On 7/28/2010 7:00 PM, pete wrote:
    >
    > #define xyz(a,b,c,jkl) {\
    >


    Thanks, but I can't actually do this. I simplified my problem, and am
    actually using a variadic argument list.
     
    Ann O'Nymous, Jul 29, 2010
    #2
    1. Advertising

  3. Ann O'Nymous <> writes:

    > On 7/28/2010 7:00 PM, pete wrote:
    >>
    >> #define xyz(a,b,c,jkl) {\

    >
    > Thanks, but I can't actually do this. I simplified my problem, and am
    > actually using a variadic argument list.


    Without the actual code (including the full range of calls that might
    be made) lots of answers may be wasted.

    There is a big picture question that might help to have answered. Why
    not use a function? The answer may be that you can't re-write the two
    called functions to take a va_list, but that as least rules out the
    obvious solution.

    --
    Ben.
     
    Ben Bacarisse, Jul 29, 2010
    #3
  4. Ann O'Nymous

    Ann O'Nymous Guest

    On 7/29/2010 9:50 AM, Ben Bacarisse wrote:
    > Ann O'Nymous<> writes:
    >
    >> On 7/28/2010 7:00 PM, pete wrote:
    >>>
    >>> #define xyz(a,b,c,jkl) {\

    >>
    >> Thanks, but I can't actually do this. I simplified my problem, and am
    >> actually using a variadic argument list.

    >
    > Without the actual code (including the full range of calls that might
    > be made) lots of answers may be wasted.
    >
    > There is a big picture question that might help to have answered. Why
    > not use a function? The answer may be that you can't re-write the two
    > called functions to take a va_list, but that as least rules out the
    > obvious solution.


    OK. I simplified things so I'd get a generic answer so I'd know what to
    do next time. This is what I have at the moment:

    void buildlist(unsigned int *,...);
    int zlink(int(int,...),int,unsigned int *);

    #define LINKX(routine,flags,...)\
    {unsigned int list[MAXARGS];\
    buildlist(list,__VA_ARGS__);\
    j = zlink((routine),(flags),list);\
    }

    "routine" is a function (one of many) called by zlink with a specialized
    parameter list in array list, and the functions cannot be changed. It
    returns int.

    zlink() cannot be changed.

    The "j=zlink()" is a hack to get the return value out.

    Calls are like this:

    int returnvalue1,returnvalue2;
    int j;
    int module1(int,...),module2(int,...);
    ....
    LINKX(module1,flag,1,2,3);
    returnvalue1=j;
    ....
    LINKX(module2,flag2,4,5,6,7,8,9);
    returnvalue2=j;
    ....
    I'd like to eliminate the "j=zlink() hack and change things so calls are
    like this:

    returnvalue1 = LINKX(module1,flag,1,2,3);
     
    Ann O'Nymous, Jul 29, 2010
    #4
  5. On Jul 29, 1:06 pm, Ann O'Nymous <> wrote:
    > void buildlist(unsigned int *,...);
    > int zlink(int(int,...),int,unsigned int *);
    >
    > #define LINKX(routine,flags,...)\
    >    {unsigned int list[MAXARGS];\
    >    buildlist(list,__VA_ARGS__);\
    >    j = zlink((routine),(flags),list);\
    >    }
    >
    > "routine" is a function (one of many) called by zlink with a specialized
    > parameter list in array list, and the functions cannot be changed.  It
    > returns int.
    >
    > zlink() cannot be changed.
    >


    > The "j=zlink()" is a hack to get the return value out.
    >
    > Calls are like this:
    >
    > int returnvalue1,returnvalue2;
    > int j;
    > int module1(int,...),module2(int,...);
    > ...
    > LINKX(module1,flag,1,2,3);
    > returnvalue1=j;
    > ...
    > LINKX(module2,flag2,4,5,6,7,8,9);
    > returnvalue2=j;
    > ...
    > I'd like to eliminate the "j=zlink() hack and change things so calls are
    > like this:
    >
    > returnvalue1 = LINKX(module1,flag,1,2,3);


    Why not put the return value as a LINKX argument before the valist?
    as in
    #define LINKX(routine, flags, returnvar,...)\
    ....
    returnvar = zlink((routine),(falgs),list);

    Usage:
    LINKX(module2,flag2,returnvalue2,4,5,6,7,8,9);

    This is what pete was suggesting I'd guess, why did you think it a bad
    idea?

    -David
     
    David Resnick, Jul 29, 2010
    #5
  6. Ann O'Nymous <> writes:
    <snip>
    > OK. I simplified things so I'd get a generic answer so I'd know what
    > to do next time. This is what I have at the moment:
    >
    > void buildlist(unsigned int *,...);
    > int zlink(int(int,...),int,unsigned int *);
    >
    > #define LINKX(routine,flags,...)\
    > {unsigned int list[MAXARGS];\
    > buildlist(list,__VA_ARGS__);\
    > j = zlink((routine),(flags),list);\
    > }
    >
    > "routine" is a function (one of many) called by zlink with a
    > specialized parameter list in array list, and the functions cannot be
    > changed. It returns int.
    >
    > zlink() cannot be changed.
    >
    > The "j=zlink()" is a hack to get the return value out.
    >
    > Calls are like this:
    >
    > int returnvalue1,returnvalue2;
    > int j;
    > int module1(int,...),module2(int,...);
    > ...
    > LINKX(module1,flag,1,2,3);
    > returnvalue1=j;
    > ...
    > LINKX(module2,flag2,4,5,6,7,8,9);
    > returnvalue2=j;
    > ...
    > I'd like to eliminate the "j=zlink() hack and change things so calls
    > are like this:
    >
    > returnvalue1 = LINKX(module1,flag,1,2,3);


    What other bits of C99 can you use? If you can use compound literals
    you can turn the macro into a expression provided that you can change
    buildlist to return a pointer to its list:

    #define LINKX(routine, flags, ...)\
    zlink((routine), (flags),\
    buildlist((unsigned int[MAXARGS]){0}, __VA_ARGS__));

    Alternatively, you might be able to share the temporary array:

    #define LINKX(routine, flags, ...)\
    (buildlist(shared_list, __VA_ARGS__),\
    zlink((routine), (flags), shared_list))

    You then need to define shared_array in the containing block. If
    buildlist can use a static array and return that you could write:

    #define LINKX(routine, flags, ...)\
    zlink((routine), (flags), buildlist(__VA_ARGS__));

    There is also a gcc-specific solution using ({}).

    --
    Ben.
     
    Ben Bacarisse, Jul 29, 2010
    #6
  7. Ann O'Nymous

    Ann O'Nymous Guest

    On 7/29/2010 1:40 PM, David Resnick wrote:
    > Why not put the return value as a LINKX argument before the valist?

    ....
    > This is what pete was suggesting I'd guess, why did you think it a bad
    > idea?


    It's not a bad idea, and it's probably what I'll be doing. It just
    seems that there has to be a better way, a C function macro should be
    able to act like a function. I just want the code to look like a
    function call, since the called routines are often functions.

    However, some of the time, they are not functions, or the function
    return value is ignored, meaning the extra parameter is not really
    used.

    So, is there a way to rewrite LINKX to be able to use the syntax
    x=LINKX(module,flag,foo); or
    LINKX(module,flag,foo); ?
    If not, I'll add the extra parameter.

    Also to Kenneth B, I am aware of the "do {...} while (0)" issue and may
    do that if I have calls like you mention. In fact, I'm sure I will have
    to do that.
    Also is "x = do {...} while (0);" valid C syntax? (if so, what does x
    get set to?)
     
    Ann O'Nymous, Jul 29, 2010
    #7
  8. Ann O'Nymous <> writes:
    > On 7/29/2010 1:40 PM, David Resnick wrote:
    >> Why not put the return value as a LINKX argument before the valist?

    > ...
    >> This is what pete was suggesting I'd guess, why did you think it a bad
    >> idea?

    >
    > It's not a bad idea, and it's probably what I'll be doing. It just
    > seems that there has to be a better way, a C function macro should be
    > able to act like a function. I just want the code to look like a
    > function call, since the called routines are often functions.

    [...]

    There is no such thing as a "function macro" or a "macro function" in C.
    There are "function-like macros", but those are merely macros with
    parameters.

    Keep in mind that macro expansion is almost purely textual, and applies
    only to the macro invocation itself. For example, given:

    x = MY_MACRO(y, z);

    the expansion of MY_MACRO can't do anything with x.

    --
    Keith Thompson (The_Other_Keith) <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"
     
    Keith Thompson, Jul 29, 2010
    #8
  9. Ann O'Nymous

    Shao Miller Guest

    #define MAXARGS 10
    typedef unsigned int zlink_args[MAXARGS];

    int zlink(int(int, ...), int, unsigned int *);
    int zlink(int bar(int, ...), int flags, unsigned int *list) {
    return 12;
    }

    unsigned int *buildlist(zlink_args list, ...) {
    /* ... */
    return list;
    }

    int foo(int bar, ...) {
    return 5;
    }

    #define LINKX(routine,flags,list, ...) \
    (zlink((routine),(flags),buildlist((list), __VA_ARGS__)))

    int main(void) {
    zlink_args mylist;
    int w, x, y, z;

    w = x = y = z = 10;
    return LINKX(foo, (1 << 3) & (1 << 4), mylist, w, x, y, z);
    }
     
    Shao Miller, Jul 30, 2010
    #9
  10. Ann O'Nymous

    Shao Miller Guest

    On Jul 29, 8:34 pm, Shao Miller <> wrote:
    >   return LINKX(foo, (1 << 3) & (1 << 4), mylist, w, x, y, z);


    '|', not '&'. ;)
     
    Shao Miller, Jul 30, 2010
    #10
  11. Ann O'Nymous

    Ann O'Nymous Guest

    On 7/29/2010 8:34 PM, Shao Miller wrote:
    > #define MAXARGS 10
    > typedef unsigned int zlink_args[MAXARGS];
    >
    > int zlink(int(int, ...), int, unsigned int *);
    > int zlink(int bar(int, ...), int flags, unsigned int *list) {
    > return 12;
    > }
    >
    > unsigned int *buildlist(zlink_args list, ...) {
    > /* ... */
    > return list;
    > }
    >
    > int foo(int bar, ...) {
    > return 5;
    > }
    >
    > #define LINKX(routine,flags,list, ...) \
    > (zlink((routine),(flags),buildlist((list), __VA_ARGS__)))
    >
    > int main(void) {
    > zlink_args mylist;
    > int w, x, y, z;
    >
    > w = x = y = z = 10;
    > return LINKX(foo, (1<< 3)& (1<< 4), mylist, w, x, y, z);
    > }


    I'll probably do something like this, although I want to hide the
    zlink_args stuff in the macro. Thanks.
     
    Ann O'Nymous, Jul 30, 2010
    #11
  12. Ann O'Nymous

    Shao Miller Guest

    On Jul 30, 11:39 am, Ann O'Nymous <> wrote:
    > I'll probably do something like this, although I want to hide the
    > zlink_args stuff in the macro.  Thanks.

    Could you at all be interested in sharing a bit more about your
    requirement for building the arguments into an array that's all inside
    the macro?

    For example, why use a macro at all? You could use a function that
    allocates the array, populates it from arguments, then calls 'zlink'
    and returns that call's result.

    Also, consider a loop where we don't pass 'mylist':

    enum { lim = 50 };
    int i, rc, w, x, y, z;

    w = x = y = z = 0;
    for (i = 0; i < lim; i++) {
    rc = LINKX(foo, (1 << 3) & (1 << 4), w, x, y, z);
    if (rc) {
    /* ... */
    }
    }

    If you use Ben's suggestion of C99 compound literals within your
    'LINKX' macro, you get nameless objects with automatic storage
    duration. When does their lifetime end? If it's the 'for' {} body,
    then what's to prevent allocating 50 of them above, as per 'lim'?
    That might get expensive.

    Are you trying to make minimal changes to someone else's code? Are
    you using 'setjmp()' and friends and have concerns about allocating
    something like 'mylist' in a function's body? Or maybe you don't wish
    to add such an allocation to every function using the 'LINKX' macro?
     
    Shao Miller, Jul 30, 2010
    #12
    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. Dead RAM
    Replies:
    20
    Views:
    1,170
    John Harrison
    Jul 14, 2004
  2. D Senthil Kumar

    macro name from macro?

    D Senthil Kumar, Sep 20, 2003, in forum: C Programming
    Replies:
    1
    Views:
    601
    Jack Klein
    Sep 21, 2003
  3. sounak

    to get macro name from macro value

    sounak, Nov 22, 2005, in forum: C Programming
    Replies:
    17
    Views:
    523
    Mark McIntyre
    Nov 22, 2005
  4. Patrick Kowalzick
    Replies:
    5
    Views:
    501
    Patrick Kowalzick
    Mar 14, 2006
  5. Mike Manilone

    macro inside macro

    Mike Manilone, Oct 3, 2011, in forum: C Programming
    Replies:
    8
    Views:
    490
    Mike Manilone
    Oct 6, 2011
Loading...

Share This Page