Is there any way in C to have a function that will take optional arguments? If not then how do syscalls work where the argument list is variable?
-
2take a look at varargs https://stackoverflow.com/questions/15784729/an-example-of-use-of-varargs-in-c – JonOsterman Aug 18 '17 at 17:24
-
You mean unknown count of arguments like `printf()` ? – kocica Aug 18 '17 at 17:24
-
3In your question you say “multiple”, but in the title you say “optional”. Do you mean a function which takes more than one argument, a function which might or might not take a given argument, or what? – Daniel H Aug 18 '17 at 17:25
-
2are you looking for a variadic or optionals, in C you can't have optionals, but you can do things like pass in NULL or -1 to mean default... you can also have variadics that take f(first, ...) arguments – Grady Player Aug 18 '17 at 17:27
-
Sorry - i meant optional arguments. A function which can take from 1 to N arguments. – KAM Aug 18 '17 at 17:48
-
you can see real example there https://stackoverflow.com/a/45762299/6110094 – 0___________ Aug 18 '17 at 17:51
-
@KAM You should edit your question to clarify. – Daniel H Aug 18 '17 at 17:56
-
@GradyPlayer Passing in `NULL` is problematic as `NULL` may be a `int` or a `void *`. What should code then use to get it via `va_arg(args, int_or_void_star);`? – chux - Reinstate Monica Aug 18 '17 at 19:39
-
@chux, yeah I was rambling... I mean you could pass in a nullish value for default named arguments, you never know what you are getting in a variadic unless you have them all the same size or read something like a format string. – Grady Player Aug 18 '17 at 21:01
-
@GradyPlayer I think that is the reason for C++ [`nullptr`](https://stackoverflow.com/q/20509734/2410359). – chux - Reinstate Monica Aug 18 '17 at 21:07
-
@chux, I don't think that solves anything in a variadic function, it allows disambiguation for function overloading... – Grady Player Aug 18 '17 at 21:13
-
@GradyPlayer In C, with `int foo(char *list, ...) { ... va_arg(args, void *); }` and `foo("one", "two", "tre", (void *) NULL);`, I see the casted `NULL` solving the `va_arg(args, what_type_to_use)` problem and works with your [null pointer at the end idea](https://stackoverflow.com/questions/45761922/c-function-with-optional-arguments-the-best-way?noredirect=1#comment78482025_45761922). With non-character pointers, it would be `int bar(xxx *list, ...) { ... va_arg(args, xxxd *); }` and `foo(xxx_1, xxx_2, xxx_3, (xxx *) 0);`. Hmmm, perhaps the basis for a SO question. – chux - Reinstate Monica Aug 18 '17 at 21:28
1 Answers
If you want a function that takes optional arguments, you need to use the stdarg
family of functions.
For example, suppose you have a function that takes two int
arguments and one or more optional int
arguments. You could write it as follows:
void myfunc(int x, int y, ...)
{
va_list args;
int i;
printf("x=%d, y=%d\n", x, y);
// y indicates how many optional arguments
if (y > 0) {
// initialize reading of optional args, passing in the last explicit argument
va_start(args, y);
for (i=0; i<y; i++) {
// read an optional int arg
int z = va_arg(args, int);
printf("z[%d]=%d\n", i, z);
}
// done reading optional args
va_end(args);
}
}
You need to have at least one explicitly named argument, and you have to have some way of knowing how many optional arguments there are. In this example, the argument y
indicates how many optional arguments there are.
Let's also look at a system function, open
. The man page shows the following prototypes:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
In C, you can't have two functions with the same name. If you look in the header files, you'll probably find this:
int open(const char *pathname, int flags, ...);
In this case, if the flags
argument has the O_CREAT
flag set, then it knows to read a single optional argument.
Then there's the execl
function:
int execl(const char *path, const char *arg, ...);
This function takes arg
as the first argument of a program to run, then reads optional arguments, each of which is a char *
, to read subsequent arguments. The caller is expected to pass NULL
as the last argument to indicate the end of the argument list. So when this function reads the optional arguments, it knows it's done when it reads NULL
pointer.

- 205,898
- 23
- 218
- 273
-
I think the answer should explicitly call out that you need to have some mechanism for the function to know how many arguments are passed. Something like an explicit count (as in the example); an implicit count (as `printf()` does with format specifiers or how the `open()` system call uses the `mode` argument if `O_CREAT` or `O_TMPFILE` is specified in the flags); or a sentinel (for example the last item might be 0 or -1 to indicate the end of the arguments). – Michael Burr Aug 18 '17 at 18:01
-