views:

1964

answers:

13
+12  Q: 

C default arguments

Is there a way to specify default arguments to a function in C?

+8  A: 

No, that's a C++ language feature.

Alex B
+7  A: 

Short answer: No.

Slightly longer answer: There is an old, old workaround where you pass a string that you parse for optional arguments:

int f(int arg1, double arg2, char* name, char *opt);

where opt may include "name=value" pair or something, and which you would call like

n = f(2,3.0,"foo","plot=yes save=no");

Obviously this is only occasionally useful. Generally when you want a single interface to a family of functionality.


You still find this approach in particle physics codes that are written by professional programs in c++ (like for instance ROOT). It's main advantage is that it may be extended almost indefinitely while maintaining back compatibility.

dmckee
Combine this with varargs and you've got all kinds of fun!
David Thornley
I would use a custom `struct` and have the caller make one, fill in the fields for different options, and then pass it by address, or pass `NULL` for default options.
Chris Lutz
Someone's been reading too much FORTRAN code!
Frank Krueger
+12  A: 

No.

Not even the very latest C99 standard supports this.

unwind
a simple no would have been even better ;)
KevinDTimm
@kevindtimm: That's not possible, SO mandates a minimum-length on answers. I tried. :)
unwind
Please refer to my answer. :)
chaos
+13  A: 

Not really. The only way would be to write a varargs function and manually fill in default values for arguments which the caller doesn't pass.

Eli Courtwright
I hate the lack of checking when using varargs.
dmckee
As well you should; I actually don't recommend this; I just wanted to convey that it is possible.
Eli Courtwright
However, how do you wanna check whether the caller passes the argument or not? I think for this to work, don't you have the caller to tell you that he didn't pass it? I think this makes the whole approach somewhat less usable - the caller could aswell call a function with another name.
Johannes Schaub - litb
That is definitely the problem, since there's no reliable, cross-platform way to check whether anything was passed at all or how many arguments they sent you. So varargs might work well if you have a function where it makes sense to call it like `f(5, 6, 7, NULL)` with some kind of terminating argument. I do occasionally write functions for which this might make sense, though not often, which is why I started my answer by saying, "Not really."
Eli Courtwright
The `open(2)` system call uses this for an optional argument that may be present depending on the required arguments, and `printf(3)` reads a format string that specifies how many arguments there will be. Both use varargs quite safely and effectively, and though you can certainly screw them up, `printf()` especially seems to be quite popular.
Chris Lutz
Printf is actually a bad example because C compilers actually end up checking the number of arguments you pass to printf and giving you errors if you pass the wrong number. The varargs function itself is not able to do that, since there's no function or macro to tell you how many parameters were actually passed.
Eli Courtwright
@Eli: Not all C compilers are gcc. There's some advanced compiler magic going on for it to warn when your printf() args don't match your format string. And I don't think it's possible to get similar warnings for your own variadic functions (unless they use the same style of format string).
tomlogic
+5  A: 

No.

chaos
Same workaround as for comments?
dmckee
Yup.
chaos
@chaos: what is the workaround? I can see that it is `20202020` in hex, but how do I type it?
Lazer
Trailing spaces. It doesn't work any more.
chaos
+18  A: 

Yes. :-) But not in a way you would expect.

int f1(int arg1, double arg2, char* name, char *opt);

int f2(int arg1, double arg2, char* name)
{
  return f1(arg1, arg2, name, "Some option");
}

Unfortunately, C doesn't allow you to overload methods so you'd end up with two different functions. Still, by calling f2, you'd actually be calling f1 with a default value. This is a "Don't Repeat Yourself" solution, which helps you to avoid copying/pasting existing code.

Workshop Alex
A reliable old warhorse of an idiom. I use it.
dmckee
A: 

No, but you might consider using a set of functions (or macros) to approximate using default args:

// No default args
int foo3(int a, int b, int c)
{
    return ...;
}

// Default 3rd arg
int foo2(int a, int b)
{
    return foo3(a, b, 0);  // default c
}

// Default 2nd and 3rd args
int foo1(int a)
{
    return foo3(a, 1, 0);  // default b and c
}
Loadmaster
What I said....
Workshop Alex
Ezactly.
Loadmaster
A: 

Generally no, but in gcc You may make the last parameter of funcA() optional with a macro.

In funcB() i use a special value (-1) to signal that i need the default value for the 'b' parameter.

#include <stdio.h> 

int funcA( int a, int b, ... ){ return a+b; }
#define funcA( a, ... ) funcA( a, ##__VA_ARGS__, 8 ) 


int funcB( int a, int b ){
  if( b == -1 ) b = 8;
  return a+b;
}

int main(void){
  printf("funcA(1,2): %i\n", funcA(1,2) );
  printf("funcA(1):   %i\n", funcA(1)   );

  printf("funcB(1, 2): %i\n", funcB(1, 2) );
  printf("funcB(1,-1): %i\n", funcB(1,-1) );
}
sambowry
+3  A: 

Probably the best way to do this (which may or may not be possible in your case depending on your situation) is to move to C++ and use it as 'a better C'. You can use C++ without using classes, templates, operator overloading or other advanced features.

This will give you a variant of C with function overloading and default parameters (and whatever other features you chose to use). You just have to be a little disciplined if you're really serious about using only a restricted subset of C++.

A lot of people will say it's a terrible idea to use C++ in this way, and they might have a point. But's it's just an opinion; I think it's valid to use features of C++ that you're comfortable with without having to buy into the whole thing. I think a significant part of the reason for the sucess of C++ is that it got used by an awful lot of programmers in it's early days in exactly this way.

Michael Burr
+4  A: 

Yet another option uses structs:

struct func_opts {
  int    arg1;
  char * arg2;
  int    arg3;
};

void func(int arg, struct func_opts *opts)
{
    int arg1 = 0, arg3 = 0;
    char *arg2 = "Default";
    if(opts)
      {
        if(opts.arg1)
            arg1 = opts.arg1;
        if(opts.arg2)
            arg2 = opts.arg2;
        if(opts.arg3)
            arg3 = opts.arg3;
      }
    // do stuff
}

// call with defaults
func(3, NULL);

// also call with defaults
struct func_opts opts = {0};
func(3, &opts);

// set some arguments
opts.arg3 = 3;
opts.arg2 = "Yes";
func(3, &opts);
Chris Lutz
A: 

Yes you can do somthing simulair, here you have to know the different argument lists you can get but you have the same function to handle then all.

typedef enum { my_input_set1 = 0, my_input_set2, my_input_set3} INPUT_SET;

typedef struct{
    INPUT_SET type;
    char* text;
} input_set1;

typedef struct{
    INPUT_SET type;
    char* text;
    int var;
} input_set2;

typedef struct{
    INPUT_SET type;
    int text;
} input_set3;

typedef union
{
    INPUT_SET type;
    input_set1 set1;
    input_set2 set2;
    input_set3 set3;
} MY_INPUT;

void my_func(MY_INPUT input)
{
    switch(input.type)
    {
        case my_input_set1:
        break;
        case my_input_set2:
        break;
        case my_input_set3:
        break;
        default:
        // unknown input
        break;
    }
}
eaanon01
+3  A: 

Wow, everybody is such a pessimist around here. The answer is yes.

It ain't trivial: by the end, we'll have the core function, a supporting struct, a wrapper function, and a macro around the wrapper function. In my work I have a set of macros to automate all this; once you understand the flow it'll be easy for you to do the same.

I've written this up elsewhere, so here's a detailed external link to supplement the summary here: http://modelingwithdata.org/arch/00000022.htm

We'd like to turn

double f(int i, double x)

into a function that takes defaults (i=8, x=3.14). Define a companion struct:

typedef struct {
    int i;
    double x;
} f_args;

Rename your function f_base, and define a wrapper function that sets defaults and calls the base:

double var_f(f_args in){
    int i_out = in.i ? in.i : 8;
    double x_out = in.x ? in.x : 3.14;
    return f_base(i_out, x_out);
}

Now add a macro, using C's variadic macros. This way users don't have to know they're actually populating a f_args struct and think they're doing the usual:

#define f(...) var_f((f_args){__VA_ARGS__});

OK, now all of the following would work:

f(3, 8);      //i=3, x=8
f(.i=1, 2.3); //i=1, x=2.3
f(2);         //i=2, x=3.14
f(.x=9.2);    //i=8, x=9.2

Check the rules on how compound initializers set defaults for the exact rules.

One thing that won't work: f(0), because we can't distinguish between a missing value and zero. In my experience, this is something to watch out for, but can be taken care of as the need arises---half the time your default really is zero.

I went through the trouble of writing this up because I think named arguments and defaults really do make coding in C easier and even more fun. And C is awesome for being so simple and still having enough there to make all this possible.

bk
A: 

Yes, with features of C99 you may do this. This works without defining new data structures or so and without the function having to decide at runtime how it was called, and without any computational overhead.

For a detailed explanation see my post at

http://gustedt.wordpress.com/2010/06/03/default-arguments-for-c99/

Jens

Jens Gustedt