tags:

views:

257

answers:

5

Hey,

How can i pass (and access) using C, not c++, variable parameters into a function?

void foo(char* mandatory_param, char* optional_param, char* optional_param2...)

thanks

/fmsf

+10  A: 

Use stdarg.h

You need to use va_list and then use the macros va_start, va_arg, and va_end.

For more information, see http://www.acm.uiuc.edu/webmonkeys/book/c_guide/2.10.html

mathepic
If you are going to downvote, at least say why in a comment instead of leaving me to wonder why my answer is possibly incorrect in some way.
mathepic
And lest you think va_args are the neatest thing since sliced bread, you should also read this: http://www.atalasoft.com/cs/blogs/stevehawley/archive/2006/03/16/9767.aspx
plinth
Oh my, there's a way a for a programmer to make a mistake using varargs! They must be TERRIBLE!
mathepic
+9  A: 

It sounds like you are looking for varargs.

#include <stdarg.h>
void foo(const char *fmt, ...)
{
  va_list argp;
  va_start(argp, fmt);
  int i = va_arg(argp, int);
  // Do stuff...
  va_end(argp);
}
zipcodeman
It'd probably help to read multiple arguments in the example, and to show stopping with a sentinel, since that's different from most languages
Michael Mrozek
+5  A: 

Read about Variable Arguments in C

gautam kumar
Why a downvote?...
gautam kumar
@gautam kumar: probably because all you did was provide a link, instead of putting some of the answer here and providing an external reference for more information.
Jefromi
Providing a useful, directly relevant link should not be considered a reason to downvote.
Mike Pelley
+1 for using a link. Why duplicate what's already there? Why summarize what's already made plain?
apollodude217
Perhaps because his answer was posted within 1-2 minutes of the other two that are voted higher, and 6 minutes of the question being asked. Let's see, how picky and ungrateful can we get over the quality of a correct answer? :-P
Quinn Taylor
A: 

In a language that does not support optional parameters directly, there are a few ways to achieve a similar effect. I will list them in order from the least versatile to the most:

  1. Create multiple overloads of the same function. As I recall, you cannot do this in C.

  2. Use variadic functions. Just Google this: http://www.google.com/search?q=variadic+function+c

  3. I recommend this: Create a "params" or "args" class (or struct in C), like this:

)

// untested C code
struct FooArgs {
    char * mandatory_param;
    char * optional_param;
    char * optional_param2;
    // add other params here;
};

and then make your method call take in a single argument:

// untested
void foo(struct fooArgs * args)

This way, as needs change, you can add parameters to fooArgs without breaking anything.

apollodude217
that should be "void foo(struct FooArgs* args)", but most people would probably use a typedef on the struct to simplify things.
mathepic
@mathepic Thanks; updated.
apollodude217
Why the downvote?
apollodude217
Probably because the question was clarified (before your answer was posted, mind you) to ask about passing "variable number of" rather than "optional" parameters. You might consider revising your question or removing it.
Quinn Taylor
+1 for thinking out of the box. It's not because the OP has asked a very specific question that an answer that uses another way of tackling a similar problem is bad. apollodude217's answer is interesting and can even be used in call chains.
tristopia
+1  A: 
#include <stdarg.h>

void do_sth (int foo, ...)
{
    int baz = 7;             /* "baz" argument */
    const char *xyz = "xyz"; /* "xyz" argument */

    /* Parse named parameters */
    va_list ap;
    va_start (ap, foo);
    for (;;) {
        const char *key = va_arg (ap, char *);
        if (key == NULL) {
            /* Terminator */
            break;
        } else if (strcmp (key, "baz") == 0) {
            baz = va_arg (ap, int);
        } else if (strcmp (key, "xyz") == 0) {
            xyz = va_arg (ap, char *);
        } else {
            /* Handle error */
        }
    }
    va_end (ap);

    /* do something useful */
}

do_sth (1, NULL);                             // no named parameters
do_sth (2, "baz", 12, NULL);                  // baz = 12
do_sth (3, "xyz", "foobaz", NULL);            // xyz = "foobaz"
do_sth (4, "baz", 12, "xyz", "foobaz", NULL); // baz = 12, xyz = "foobaz"

http://stackoverflow.com/questions/2826128/variadic-functions-and-arguments-assignment-in-c-c/2826411#2826411

el.pescado