Dynamic no. of arguments

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • squaretriangle@hotmail.co.uk

    Dynamic no. of arguments

    Is it possible through some trickery, perhaps using the methods of
    stdarg, to pass a dynamic (unknown at compile time) number of
    arguments to a function? For example, I want to enumerate an array of
    values and then pass them all to sprintf. I wouldn't want to write an
    explicit check for each amount of variables that I might want to send,
    nor write my own sprintf function that takes an array. Can it be done?
  • user923005

    #2
    Re: Dynamic no. of arguments

    On Jun 10, 8:29 pm, squaretrian...@ hotmail.co.uk wrote:
    Is it possible through some trickery, perhaps using the methods of
    stdarg, to pass a dynamic (unknown at compile time) number of
    arguments to a function?  For example, I want to enumerate an array of
    values and then pass them all to sprintf.  I wouldn't want to write an
    explicit check for each amount of variables that I might want to send,
    nor write my own sprintf function that takes an array.  Can it be done?
    Probably, I don't understand your question properly. Maybe 15.3,4
    From the C-FAQ will help:

    15.4: How can I write a function that takes a variable number of
    arguments?

    A: Use the facilities of the <stdarg.hheader .

    Here is a function which concatenates an arbitrary number of
    strings into malloc'ed memory:

    #include <stdlib.h/* for malloc, NULL, size_t */
    #include <stdarg.h/* for va_ stuff */
    #include <string.h/* for strcat et al. */

    char *vstrcat(const char *first, ...)
    {
    size_t len;
    char *retbuf;
    va_list argp;
    char *p;

    if(first == NULL)
    return NULL;

    len = strlen(first);

    va_start(argp, first);

    while((p = va_arg(argp, char *)) != NULL)
    len += strlen(p);

    va_end(argp);

    retbuf = malloc(len + 1); /* +1 for trailing \0 */

    if(retbuf == NULL)
    return NULL; /* error */

    (void)strcpy(re tbuf, first);

    va_start(argp, first); /* restart; 2nd scan */

    while((p = va_arg(argp, char *)) != NULL)
    (void)strcat(re tbuf, p);

    va_end(argp);

    return retbuf;
    }

    Usage is something like

    char *str = vstrcat("Hello, ", "world!", (char *)NULL);

    Note the cast on the last argument; see questions 5.2 and 15.3.
    (Also note that the caller must free the returned, malloc'ed
    storage.)

    References: K&R2 Sec. 7.3 p. 155, Sec. B7 p. 254; ISO Sec. 7.8;
    Rationale Sec. 4.8; H&S Sec. 11.4 pp. 296-9; CT&P Sec. A.3 pp.
    139-141; PCS Sec. 11 pp. 184-5, Sec. 13 p. 242.

    15.5: How can I write a function that takes a format string and a
    variable number of arguments, like printf(), and passes them to
    printf() to do most of the work?

    A: Use vprintf(), vfprintf(), or vsprintf().

    Here is an error() function which prints an error message,
    preceded by the string "error: " and terminated with a newline:

    #include <stdio.h>
    #include <stdarg.h>

    void error(const char *fmt, ...)
    {
    va_list argp;
    fprintf(stderr, "error: ");
    va_start(argp, fmt);
    vfprintf(stderr , fmt, argp);
    va_end(argp);
    fprintf(stderr, "\n");
    }

    References: K&R2 Sec. 8.3 p. 174, Sec. B1.2 p. 245; ISO
    Secs. 7.9.6.7,7.9.6.8 ,7.9.6.9; H&S Sec. 15.12 pp. 379-80; PCS
    Sec. 11 pp. 186-7.

    Comment

    • Richard Heathfield

      #3
      Re: Dynamic no. of arguments

      squaretriangle@ hotmail.co.uk said:
      Is it possible through some trickery, perhaps using the methods of
      stdarg, to pass a dynamic (unknown at compile time) number of
      arguments to a function?
      Put the values in an array, and pass a pointer (to the array's first
      element) to the function, along with a count. In the function itself, use
      a loop to process the data.
      For example, I want to enumerate an array of
      values and then pass them all to sprintf. I wouldn't want to write an
      explicit check for each amount of variables that I might want to send,
      nor write my own sprintf function that takes an array. Can it be done?
      Write a wrapper that uses the technique given above to receive the data and
      passes it to sprintf in a loop. Be real sure you have enough space to
      store all the data in the string.

      --
      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

      • rahul

        #4
        Re: Dynamic no. of arguments

        On Jun 11, 8:29 am, squaretrian...@ hotmail.co.uk wrote:
        Is it possible through some trickery, perhaps using the methods of
        stdarg, to pass a dynamic (unknown at compile time) number of
        arguments to a function? For example, I want to enumerate an array of
        values and then pass them all to sprintf. I wouldn't want to write an
        explicit check for each amount of variables that I might want to send,
        nor write my own sprintf function that takes an array. Can it be done?
        From your requirements, it looks like vsnprintf can do the trick for
        you.
        Whiel using the v*f family of functions, one thing to be taken care of
        is
        va_start() and va_end() has to be called explicitly. Forgetting to
        call
        va_end() may result in undefined behavior.

        Quoting the manual:
        The functions vprintf(), vfprintf(), vsprintf(), vsnprintf()
        are equivalent to the func-
        tions printf(), fprintf(), sprintf(), snprintf(),
        respectively, except that they are
        called with a va_list instead of a variable number of
        arguments. These functions do not
        call the va_end macro. Consequently, the value of ap is
        undefined after the call. The
        application should call va_end(ap) itself afterwards.

        Comment

        • CBFalconer

          #5
          Re: Dynamic no. of arguments

          squaretriangle@ hotmail.co.uk wrote:
          >
          Is it possible through some trickery, perhaps using the methods
          of stdarg, to pass a dynamic (unknown at compile time) number of
          arguments to a function? For example, I want to enumerate an
          array of values and then pass them all to sprintf. I wouldn't
          want to write an explicit check for each amount of variables that
          I might want to send, nor write my own sprintf function that
          takes an array. Can it be done?
          Yes, we do it all the time with lists. For trickless example:

          struct listobj {
          struct listobj *next;
          void *datum;
          }

          /* ... */

          void operateon(struc t listobj *root) {
          while (root) {
          /* do things with root->datum */
          root = root->next;
          }
          } /* operateon */

          --
          [mail]: Chuck F (cbfalconer at maineline dot net)
          [page]: <http://cbfalconer.home .att.net>
          Try the download section.


          ** Posted from http://www.teranews.com **

          Comment

          • squaretriangle@hotmail.co.uk

            #6
            Re: Dynamic no. of arguments

            On Jun 11, 7:30 am, CBFalconer <cbfalco...@yah oo.comwrote:
            squaretrian...@ hotmail.co.uk wrote:
            >
            Is it possible through some trickery, perhaps using the methods
            of stdarg, to pass a dynamic (unknown at compile time) number of
            arguments to a function? For example, I want to enumerate an
            array of values and then pass them all to sprintf. I wouldn't
            want to write an explicit check for each amount of variables that
            I might want to send, nor write my own sprintf function that
            takes an array. Can it be done?
            >
            Yes, we do it all the time with lists. For trickless example:
            >
            struct listobj {
            struct listobj *next;
            void *datum;
            >
            }
            >
            /* ... */
            >
            void operateon(struc t listobj *root) {
            while (root) {
            /* do things with root->datum */
            root = root->next;
            }
            >
            } /* operateon */
            >
            That's passing a single argument that is the head of a linked list. I
            was talking about passing an unknown number of arguments to a function
            that uses ellipses. Hence why I mention sprintf.

            Comment

            • squaretriangle@hotmail.co.uk

              #7
              Re: Dynamic no. of arguments

              On Jun 11, 5:55 am, Richard Heathfield <r...@see.sig.i nvalidwrote:
              squaretrian...@ hotmail.co.uk said:
              >
              Is it possible through some trickery, perhaps using the methods of
              stdarg, to pass a dynamic (unknown at compile time) number of
              arguments to a function?
              >
              Put the values in an array, and pass a pointer (to the array's first
              element) to the function, along with a count. In the function itself, use
              a loop to process the data.
              >
              For example, I want to enumerate an array of
              values and then pass them all to sprintf. I wouldn't want to write an
              explicit check for each amount of variables that I might want to send,
              nor write my own sprintf function that takes an array. Can it be done?
              >
              Write a wrapper that uses the technique given above to receive the data and
              passes it to sprintf in a loop. Be real sure you have enough space to
              store all the data in the string.
              No, I want sprintf to be only called once. My situation is that I
              have an interpreted language that I want to add an sprintf function
              for, the internal function for which accepts a list of arguments in an
              array, and then simply passes it on to the standard c library's own
              sprintf function, _somehow_ passing that array off as the last
              argument to sprintf and having it accept it. I don't want to have to
              iterate the string or array nor call sprintf repeatedly.

              I'm guessing this is not possible.

              Comment

              • Keith Thompson

                #8
                Re: Dynamic no. of arguments

                squaretriangle@ hotmail.co.uk writes:
                On Jun 11, 7:30 am, CBFalconer <cbfalco...@yah oo.comwrote:
                >squaretrian... @hotmail.co.uk wrote:
                Is it possible through some trickery, perhaps using the methods
                of stdarg, to pass a dynamic (unknown at compile time) number of
                arguments to a function? For example, I want to enumerate an
                array of values and then pass them all to sprintf. I wouldn't
                want to write an explicit check for each amount of variables that
                I might want to send, nor write my own sprintf function that
                takes an array. Can it be done?
                >>
                >Yes, we do it all the time with lists. For trickless example:
                >>
                [example snipped]
                >>
                >
                That's passing a single argument that is the head of a linked list. I
                was talking about passing an unknown number of arguments to a function
                that uses ellipses. Hence why I mention sprintf.
                It's not possible to *directly* pass a dynamic number of arguments in
                a function call. When you write the call in your source code, that
                call includes a number of arguments; that number is fixed when you
                write it.

                There are various indirect ways to accomplish the same thing.

                --
                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

                • Eric Sosman

                  #9
                  Re: Dynamic no. of arguments

                  squaretriangle@ hotmail.co.uk wrote:
                  Is it possible through some trickery, perhaps using the methods of
                  stdarg, to pass a dynamic (unknown at compile time) number of
                  arguments to a function? For example, I want to enumerate an array of
                  values and then pass them all to sprintf. I wouldn't want to write an
                  explicit check for each amount of variables that I might want to send,
                  nor write my own sprintf function that takes an array. Can it be done?
                  No. A function call supplies a fixed number of argument
                  values, and that number cannot be changed after compilation.
                  "Variadic" functions can be called with different numbers of
                  arguments, but that just means that they can be called from
                  many different sites whose fixed argument counts disagree with
                  each other.

                  Some compilers provide ways to construct argument lists on
                  the fly and to pass them to called functions, but the mechanisms
                  (if they exist at all) are compiler-specific extensions to C
                  and not part of the language. You should use such things only
                  if (1) they solve your larger problem, (2) there's no hope of
                  solving your problem by standard means, (3) you don't mind tying
                  your code forever to one particular compiler, and (4) the
                  capability actually exists.

                  From what you've described, I'm not convinced your need
                  meets criterion #1 and am virtually certain it doesn't pass #2.
                  You want to pass an array of values to one sprintf() call --
                  well, what does the format string look like? If you need a
                  loop to build a format string with the right number of "%d"'s
                  in it, why not just sprintf() the array's values one by one in
                  the loop? Why work extra hard to use a non-portable construct
                  in preference to a simpler and entirely portable construct?

                  --
                  Eric.Sosman@sun .com

                  Comment

                  • squaretriangle@hotmail.co.uk

                    #10
                    Re: Dynamic no. of arguments

                    On Jun 11, 6:13 pm, Eric Sosman <Eric.Sos...@su n.comwrote:
                    You want to pass an array of values to one sprintf() call --
                    well, what does the format string look like? If you need a
                    loop to build a format string with the right number of "%d"'s
                    in it, why not just sprintf() the array's values one by one in
                    the loop? Why work extra hard to use a non-portable construct
                    in preference to a simpler and entirely portable construct?
                    It wasn't about meeting a need; I just idly wondered if it could be
                    done. :)

                    Comment

                    • CBFalconer

                      #11
                      Re: Dynamic no. of arguments

                      squaretriangle@ hotmail.co.uk wrote:
                      CBFalconer <cbfalco...@yah oo.comwrote:
                      >squaretrian... @hotmail.co.uk wrote:
                      >>
                      >>Is it possible through some trickery, perhaps using the methods
                      >>of stdarg, to pass a dynamic (unknown at compile time) number of
                      >>arguments to a function? For example, I want to enumerate an
                      >>array of values and then pass them all to sprintf. I wouldn't
                      >>want to write an explicit check for each amount of variables that
                      >>I might want to send, nor write my own sprintf function that
                      >>takes an array. Can it be done?
                      >>
                      >Yes, we do it all the time with lists. For trickless example:
                      >>
                      >struct listobj {
                      > struct listobj *next;
                      > void *datum;
                      >}
                      >>
                      >/* ... */
                      >>
                      >void operateon(struc t listobj *root) {
                      > while (root) {
                      > /* do things with root->datum */
                      > root = root->next;
                      > }
                      >>
                      >} /* operateon */
                      >
                      That's passing a single argument that is the head of a linked list.
                      I was talking about passing an unknown number of arguments to a
                      function that uses ellipses. Hence why I mention sprintf.
                      No, that is passing an unknown number of arguments for processing,
                      controlled only by the length of the list. If you wish, you can
                      have the caller form the list, and you can have the user destroy
                      it. Think about it.

                      --
                      [mail]: Chuck F (cbfalconer at maineline dot net)
                      [page]: <http://cbfalconer.home .att.net>
                      Try the download section.


                      ** Posted from http://www.teranews.com **

                      Comment

                      • Keith Thompson

                        #12
                        Re: Dynamic no. of arguments

                        CBFalconer <cbfalconer@yah oo.comwrites:
                        squaretriangle@ hotmail.co.uk wrote:
                        >CBFalconer <cbfalco...@yah oo.comwrote:
                        >>squaretrian.. .@hotmail.co.uk wrote:
                        >>>
                        >>>Is it possible through some trickery, perhaps using the methods
                        >>>of stdarg, to pass a dynamic (unknown at compile time) number of
                        >>>arguments to a function? For example, I want to enumerate an
                        >>>array of values and then pass them all to sprintf. I wouldn't
                        >>>want to write an explicit check for each amount of variables that
                        >>>I might want to send, nor write my own sprintf function that
                        >>>takes an array. Can it be done?
                        >>>
                        >>Yes, we do it all the time with lists. For trickless example:
                        >>>
                        >>struct listobj {
                        >> struct listobj *next;
                        >> void *datum;
                        >>}
                        >>>
                        >>/* ... */
                        >>>
                        >>void operateon(struc t listobj *root) {
                        >> while (root) {
                        >> /* do things with root->datum */
                        >> root = root->next;
                        >> }
                        >>>
                        >>} /* operateon */
                        >>
                        >That's passing a single argument that is the head of a linked list.
                        >I was talking about passing an unknown number of arguments to a
                        >function that uses ellipses. Hence why I mention sprintf.
                        >
                        No, that is passing an unknown number of arguments for processing,
                        controlled only by the length of the list. If you wish, you can
                        have the caller form the list, and you can have the user destroy
                        it. Think about it.
                        No, that is passing a single argument, where an "argument" is an
                        "expression in the comma-separated list bounded by the parentheses in
                        a function call expression" (C99 3.3).

                        The called function can, of course, use the value of that argument to
                        access an arbitrary number of nodes in the linked list. This may be
                        just as good for most purposes as actually passing an arbitrary number
                        of arguments. However, it doesn't directly address the OP's query
                        about passing an arbitrary list of arguments to sprintf.

                        I was thinking that vsprintf() might be helpful, but I don't see any
                        way to build the required va_list dynamically.

                        --
                        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

                        • Antoninus Twink

                          #13
                          Re: Dynamic no. of arguments

                          On 12 Jun 2008 at 1:33, Keith Thompson wrote:
                          CBFalconer <cbfalconer@yah oo.comwrites:
                          [snip garbage]
                          However, it doesn't directly address the OP's query about passing an
                          arbitrary list of arguments to sprintf.
                          No surprise there then.

                          The OP could find out what the calling conventions are on his system,
                          and use inline assembly to (let's say) push some number of arguments
                          to be determined at runtime onto the stack, and call sprintf.

                          Comment

                          • Kaz Kylheku

                            #14
                            Re: Dynamic no. of arguments

                            On Jun 10, 8:29 pm, squaretrian...@ hotmail.co.uk wrote:
                            Is it possible through some trickery, perhaps using the methods of
                            stdarg, to pass a dynamic (unknown at compile time) number of
                            arguments to a function?
                            There is no portable way to call an arbitrarily declared function.

                            Being able to do such a thing, however, is very useful in the
                            implementation of high level programming languages which need dynamic
                            foreign function calling (in both directions).

                            Bruno Haible has developed a collection of libraries for doing this:



                            This is GPLed stuff, though, and though it's ported to a number of
                            architectures, the list is far from exhaustive. But this project does
                            give us an API for doing this, and proves that it's feasible by
                            demonstrating a working implementation that is used in real projects.

                            Comment

                            • Kenny McCormack

                              #15
                              Re: Dynamic no. of arguments

                              In article <slrng51lsv.8v5 .nospam@nospam. invalid>,
                              Antoninus Twink <nospam@nospam. invalidwrote:
                              >On 12 Jun 2008 at 1:33, Keith Thompson wrote:
                              >CBFalconer <cbfalconer@yah oo.comwrites:
                              >[snip garbage]
                              >However, it doesn't directly address the OP's query about passing an
                              >arbitrary list of arguments to sprintf.
                              >
                              >No surprise there then.
                              >
                              >The OP could find out what the calling conventions are on his system,
                              >and use inline assembly to (let's say) push some number of arguments
                              >to be determined at runtime onto the stack, and call sprintf.
                              >
                              Actually, the real answer to the OP's question is: avcall
                              Google it.

                              It works on all the common major platforms, and is quite well done.

                              Comment

                              Working...