variadic arithmetic, boolean operators

Discussion in 'C Programming' started by Trent Buck, Jan 1, 2005.

  1. Trent Buck

    Trent Buck Guest

    (Note: C99 supports variadic macros, but C89 does not.)

    I'm pretty sure what I'm trying to do is impossible, but I'll ask here
    in case I'm missing something.

    I'm trying to define generic, variadic arithmetic and boolean operators.
    For example,

    product (2, sum (3, 4), 5);

    should expand to

    (2) * ((3) + (4)) * (5);

    Here is my pseudocode:

    #define sum(x,y) \
    (x) + (y)

    #define sum(x, y, ...) \
    (x) + sum (y, __VA_ARGS__)

    int main (void)
    {
    sum (1, 2, 3, 4);
    return 0;
    }

    Unfortunately, this has two problems:

    - Macros cannot be overriden, hence the base case cannot be caught
    generically. (You can define the base case as a function if the
    definition (and declaration) precede the macro definition.)

    - Macros expansion is not recursive (apparently).

    For example, GCC's preprocessor outputs the following:

    tmp.c:4:1: warning: "sum" redefined
    tmp.c:1:1: warning: this is the location of the previous definition
    # 1 "tmp.c"
    # 1 "<built-in>"
    # 1 "<command line>"
    # 1 "tmp.c"






    int main (void)
    {
    (1) + sum (2, 3, 4);
    return 0;
    }

    Can someone please either confirm that this is impossible in C, or
    suggest how to go about it?

    --
    -trent
    Physics is what results when you pollute mathematics with reality.
     
    Trent Buck, Jan 1, 2005
    #1
    1. Advertising

  2. Trent Buck wrote:
    > (Note: C99 supports variadic macros, but C89 does not.)
    >
    > I'm pretty sure what I'm trying to do is impossible, but I'll ask here
    > in case I'm missing something.
    >
    > I'm trying to define generic, variadic arithmetic and boolean operators.
    > For example,
    >
    > product (2, sum (3, 4), 5);
    >
    > should expand to
    >
    > (2) * ((3) + (4)) * (5);
    >
    > Here is my pseudocode:
    >
    > #define sum(x,y) \
    > (x) + (y)
    >
    > #define sum(x, y, ...) \
    > (x) + sum (y, __VA_ARGS__)
    >
    > int main (void)
    > {
    > sum (1, 2, 3, 4);
    > return 0;
    > }
    >
    > Unfortunately, this has two problems:
    >
    > - Macros cannot be overriden, hence the base case cannot be caught
    > generically. (You can define the base case as a function if the
    > definition (and declaration) precede the macro definition.)
    >
    > - Macros expansion is not recursive (apparently).


    My suggestion is to change your design so that you are passing
    containers (lists, vectors, arrays, etc.) to each function. Each
    function would return the result. This design would eliminate
    the need for variable argument lists.

    int sum(int * array_of_integers,
    unsigned int num_integers)
    {
    int result;
    unsigned int index;
    for (index = 0, result = 0;
    index < num_integers;
    ++index)
    {
    result += *array_of_integers++;
    }
    return result;
    }


    --
    Thomas Matthews

    C++ newsgroup welcome message:
    http://www.slack.net/~shiva/welcome.txt
    C++ Faq: http://www.parashift.com/c -faq-lite
    C Faq: http://www.eskimo.com/~scs/c-faq/top.html
    alt.comp.lang.learn.c-c++ faq:
    http://www.comeaucomputing.com/learn/faq/
    Other sites:
    http://www.josuttis.com -- C++ STL Library book
    http://www.sgi.com/tech/stl -- Standard Template Library
     
    Thomas Matthews, Jan 1, 2005
    #2
    1. Advertising

  3. Trent Buck

    Trent Buck Guest

    Up spake Thomas Matthews:
    > My suggestion is to change your design so that you are passing
    > containers (lists, vectors, arrays, etc.) to each function. Each
    > function would return the result. This design would eliminate
    > the need for variable argument lists.


    Not a solution I'm particularly taken with, but better than anything I
    had come up with. Thank you.

    --
    -trent
    Turn off your targeting computer, Luke. ASS. AHS. You have a better
    chance of making this shot by guessing.
     
    Trent Buck, Jan 1, 2005
    #3
  4. Trent Buck

    Mysidia Guest

    If using gcc, I might say use the ({}) extension:

    #define sum(s...) \
    ({ int args[] = { s }; \
    mysum(args, sizeof(args)/sizeof(*args)); \
    })

    int mysum(int args[], int n)
    {
    int i,w=0;

    for(i=0;i<n;i++) w+= args;
    return w;
    };


    For C99, perhaps a make_list macro could be a useful
    approach... so you would have

    make_list(list, 3,4,5,6)
    sum(list);

    struct List {
    int *arr;
    int len;
    };

    #define make_list(L,...) \
    do {
    int args[] = { __VA_ARGS__ };
    int len = sizeof(args) / sizeof(*args);
    L.args = args;
    L.len = len;
    } while(0)


    -Jmh
     
    Mysidia, Jan 2, 2005
    #4
    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. Colin Walters
    Replies:
    2
    Views:
    525
    Ben Pfaff
    Feb 13, 2004
  2. Ross A. Finlayson
    Replies:
    19
    Views:
    602
    Keith Thompson
    Mar 10, 2005
  3. Replies:
    2
    Views:
    350
    Dave Thompson
    Feb 27, 2006
  4. Replies:
    5
    Views:
    367
  5. J Leonard
    Replies:
    4
    Views:
    12,688
    Mark Space
    Jan 19, 2008
Loading...

Share This Page