variable number of arguments

Discussion in 'C Programming' started by The Directive, Jan 11, 2004.

  1. I read the C FAQ question on passing a variable number of arguments,
    but it didn't help. The example assumes all arguments are of the same
    type.

    I want to create a function "trace" that can be used like this:

    trace( "Err", errtType, lineNum, NULL) /* where errType is char* and
    lineNum is
    an int */

    trace("Err", lineNum, NULL);

    trace( lineNum, "Err", funcName, NULL) /* where funName is char * */

    The problem is that I don't know the order and the variable types of
    the arguments passed.

    How can I implement trace?
    The Directive, Jan 11, 2004
    #1
    1. Advertising

  2. The Directive

    Ben Pfaff Guest

    (The Directive) writes:

    > I want to create a function "trace" that can be used like this:
    >
    > trace( "Err", errtType, lineNum, NULL) /* where errType is char* and
    > lineNum is
    > an int */
    >
    > trace("Err", lineNum, NULL);
    >
    > trace( lineNum, "Err", funcName, NULL) /* where funName is char * */
    >
    > The problem is that I don't know the order and the variable types of
    > the arguments passed.
    >
    > How can I implement trace?


    You can't. trace() has to know the types of the arguments, or be
    able to figure them out.
    --
    int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.\
    \n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
    );while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p\
    );}return 0;}
    Ben Pfaff, Jan 11, 2004
    #2
    1. Advertising

  3. The Directive

    DomiPi Guest

    Hi
    I already wrote a function of the same type. But I believe that it is
    necessary to have at least a parameter which will describe the following.
    Like does it printf, you could have: trace(char format,...);
    with for example:
    trace("Err Line:%d Type:%c File name:%s,__LINE__,mytype,__FILE__);
    If you want, I can send my source
    Dominique

    "The Directive" <> a écrit dans le message de
    news:...
    > I read the C FAQ question on passing a variable number of arguments,
    > but it didn't help. The example assumes all arguments are of the same
    > type.
    >
    > I want to create a function "trace" that can be used like this:
    >
    > trace( "Err", errtType, lineNum, NULL) /* where errType is char* and
    > lineNum is
    > an int */
    >
    > trace("Err", lineNum, NULL);
    >
    > trace( lineNum, "Err", funcName, NULL) /* where funName is char * */
    >
    > The problem is that I don't know the order and the variable types of
    > the arguments passed.
    >
    > How can I implement trace?
    DomiPi, Jan 11, 2004
    #3
  4. The Directive

    DomiPi Guest

    Oups error:
    trace(char *format, ...);

    "DomiPi" <> a écrit dans le message de
    news:btsbp4$kbv$...
    > Hi
    > I already wrote a function of the same type. But I believe that it is
    > necessary to have at least a parameter which will describe the following.
    > Like does it printf, you could have: trace(char format,...);
    > with for example:
    > trace("Err Line:%d Type:%c File name:%s,__LINE__,mytype,__FILE__);
    > If you want, I can send my source
    > Dominique
    >
    > "The Directive" <> a écrit dans le message de
    > news:...
    > > I read the C FAQ question on passing a variable number of arguments,
    > > but it didn't help. The example assumes all arguments are of the same
    > > type.
    > >
    > > I want to create a function "trace" that can be used like this:
    > >
    > > trace( "Err", errtType, lineNum, NULL) /* where errType is char* and
    > > lineNum is
    > > an int */
    > >
    > > trace("Err", lineNum, NULL);
    > >
    > > trace( lineNum, "Err", funcName, NULL) /* where funName is char * */
    > >
    > > The problem is that I don't know the order and the variable types of
    > > the arguments passed.
    > >
    > > How can I implement trace?

    >
    >
    DomiPi, Jan 11, 2004
    #4
  5. "DomiPi" <> wrote in message
    news:btscec$l47$...
    > Oups error:
    > trace(char *format, ...);


    Oups (sic) error: top-post.

    <rest snipped for clarity>

    Peter
    Peter Pichler, Jan 11, 2004
    #5
  6. "DomiPi" <> writes:
    > I already wrote a function of the same type. But I believe that it is
    > necessary to have at least a parameter which will describe the following.
    > Like does it printf, you could have: trace(char format,...);
    > with for example:
    > trace("Err Line:%d Type:%c File name:%s,__LINE__,mytype,__FILE__);
    > If you want, I can send my source


    There are a number of ways that a function taking a variable number of
    arguments can be told the number and type of the arguments. printf's
    format string is probably the most common. If all the arguments
    (after the initial one(s)) are of the same type, a sentinel value,
    such as a null pointer, can be used to mark the end of the list.

    Another approach (one that I've never actually seen) is for every
    other argument to specify the type of the following one:

    foo('i', 42,
    'd', 123.4,
    's', "hello");

    Whatever method is used, it's the caller's responsibility to make sure
    everything is consistent. If you pass a pointer where the function
    looks for an int, you're not likely to get any help from the compiler.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
    Schroedinger does Shakespeare: "To be *and* not to be"
    Keith Thompson, Jan 11, 2004
    #6
  7. The Directive

    CBFalconer Guest

    Peter Pichler wrote:
    > "DomiPi" <> wrote in message
    >
    > > Oups error:
    > > trace(char *format, ...);

    >
    > Oups (sic) error: top-post.
    >
    > <rest snipped for clarity>


    A fine riposte.

    --
    Chuck F () ()
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net> USE worldnet address!
    CBFalconer, Jan 12, 2004
    #7
  8. From everyone's responses, I conclude that there's no easy, clean way
    to pass a variable number of arguments with variable unknown types in
    C. Correct? That information must be passed as another argument. What
    was the reasoning for the C language designers to implement it this
    way? Is it a weakness of the language?

    --The Directive

    Keith Thompson <> wrote in message news:<>...
    > "DomiPi" <> writes:
    > > I already wrote a function of the same type. But I believe that it is
    > > necessary to have at least a parameter which will describe the following.
    > > Like does it printf, you could have: trace(char format,...);
    > > with for example:
    > > trace("Err Line:%d Type:%c File name:%s,__LINE__,mytype,__FILE__);
    > > If you want, I can send my source

    >
    > There are a number of ways that a function taking a variable number of
    > arguments can be told the number and type of the arguments. printf's
    > format string is probably the most common. If all the arguments
    > (after the initial one(s)) are of the same type, a sentinel value,
    > such as a null pointer, can be used to mark the end of the list.
    >
    > Another approach (one that I've never actually seen) is for every
    > other argument to specify the type of the following one:
    >
    > foo('i', 42,
    > 'd', 123.4,
    > 's', "hello");
    >
    > Whatever method is used, it's the caller's responsibility to make sure
    > everything is consistent. If you pass a pointer where the function
    > looks for an int, you're not likely to get any help from the compiler.
    The Directive, Jan 12, 2004
    #8
  9. On Mon, 11 Jan 2004, The Directive wrote:
    >
    > From everyone's responses, I conclude that there's no easy, clean way
    > to pass a variable number of arguments with variable unknown types in
    > C. Correct? That information must be passed as another argument. What
    > was the reasoning for the C language designers to implement it this
    > way? Is it a weakness of the language?


    Please snip the part of the previous message to which you're not
    responding. And don't top-post. http://www.google.com/search?q=top post

    Now, as to your question: Correct. That information (about types)
    must be passed as another argument, or built into the structure of the
    arguments in the first place. (For example, you could pass a list of
    positive integers to a function, and end the list with -1. The
    function would know to stop reading arguments when it hit that -1.)
    The C language was designed this way because it's incredibly easy
    to code, and it's pretty fast [with relatively naive optimization], too,
    compared to other ways. Compare the C model to the "Pascal" model,
    which can't support variadic functions at all. Search Google for
    "argument passing conventions," and then try comp.compilers,
    comp.programming, or a similar group if you have implementation
    questions.
    It's a weakness of the language when compared to languages that
    provide more functionality (such as a count of arguments magically
    supplied by the compiler); but off the top of my head, the only
    language I know that does better is Matlab, and it's got its own
    weaknesses. :) It's a trade-off between ease of implementation, power,
    and user-friendliness. Since most users don't define functions where
    they don't know what they're going to be passing as arguments, it
    probably didn't seem a big deal when C was being standardized.

    Historical note: I seem to recall that in pre-1989 days, there
    was no [de facto] language support for variadic functions at all.
    printf and scanf worked by magic; the user was not generally able to
    write his own printf-alikes. Do I recall correctly?

    -Arthur
    Arthur J. O'Dwyer, Jan 12, 2004
    #9
  10. "Arthur J. O'Dwyer" <> writes:
    [...]
    > Historical note: I seem to recall that in pre-1989 days, there
    > was no [de facto] language support for variadic functions at all.
    > printf and scanf worked by magic; the user was not generally able to
    > write his own printf-alikes. Do I recall correctly?
    >
    > -Arthur


    There was a <varargs.h> header that predated the current <stdarg.h>
    header. Since <stdarg.h> is in the 1989 ANSI standard, <varargs.h>
    must have existed before 1989.

    But I think that there was a time, before <varargs.h> was invented,
    when printf and scanf worked by magic (e.g., by explicitly computing
    stack offsets for successive arguments).

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://www.sdsc.edu/~kst>
    Schroedinger does Shakespeare: "To be *and* not to be"
    Keith Thompson, Jan 12, 2004
    #10
  11. The Directive

    Ben Pfaff Guest

    Keith Thompson <> writes:

    > There was a <varargs.h> header that predated the current <stdarg.h>
    > header. Since <stdarg.h> is in the 1989 ANSI standard, <varargs.h>
    > must have existed before 1989.
    >
    > But I think that there was a time, before <varargs.h> was invented,
    > when printf and scanf worked by magic (e.g., by explicitly computing
    > stack offsets for successive arguments).


    Here's the printf() from the Lions Book circa 1976. All typos
    are mine.

    /*
    * Scaled down version of C Library printf.
    * Only %s %l %d (==%l) %o are recognized.
    * Used to print diagnostic information
    * directly on console tty.
    * Since it is not interrupt driven,
    * all system activities are pretty much
    * suspended.
    * Printf should not be used for chit-chat.
    */
    printf(fmt,x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc)
    char fmt[];
    {
    register char *s;
    register *adx, c;

    adx = &x1;
    loop:
    while((c = *fmt++) != '%') {
    if(c == '\0')
    return;
    putchar(c);
    }
    c = *fmt++;
    if(c == 'd' || c == 'l' || c == 'o')
    printn(*adx, c=='o'? 8: 10);
    if(c == 's') {
    s = *adx;
    while(c == *s++)
    puthcar(c);
    }
    adx++;
    goto loop;
    }
    --
    int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.\
    \n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
    );while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p\
    );}return 0;}
    Ben Pfaff, Jan 12, 2004
    #11
    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. Alex
    Replies:
    1
    Views:
    369
    Ron Natalie
    Oct 16, 2003
  2. markus_e
    Replies:
    4
    Views:
    493
    Andre Kostur
    Apr 7, 2004
  3. Replies:
    3
    Views:
    806
  4. Navaneeth
    Replies:
    4
    Views:
    544
    Kenny McCormack
    Nov 20, 2010
  5. oldyork90
    Replies:
    10
    Views:
    337
    Jorge
    Sep 27, 2008
Loading...

Share This Page