How can I make a function with optional arguments in C?
Solution 1
The open
function is declared as a variadic function. It will look something like this:
#include <stdarg.h>
int open(char const * filename, int flags, ...)
{
va_list ap;
va_start(ap, flags);
if (flags & O_CREAT)
{
int mode = va_arg(ap, int);
// ...
}
// ...
va_end(ap);
}
The further arguments are not consumed unless you have indicated that they do in fact exist.
The same construction is used for printf
.
The manual doesn't always make this explicit, since the only possible two signatures are (char const *, int)
and (char const *, int, int)
, so there's little point in revealing that you the function actually accepts variable arguments. (You can test this by trying to compile something like open("", 1, 2, 3, 4, 5, 6)
.)
Solution 2
In all cases, a varargs function must be able to determine somehow, from the fixed arguments, how many variable arguments there are. For example, the printf()
family of functions use the format string to determine the number and types of the arguments. The execl()
function uses a sentinel (null pointer) to mark the end of the argument list. It would be possible to use a count instead of a sentinel (but if you're going to do that, the chances are that a count and an array in a non-varargs function would work as well as, if not better than, a count and a list of arguments). The open()
function uses one of the flag bits to determine whether the mode should be present — see Kerrek SB's answer.
The main()
function is a special case. The implementation (compiler) is prohibited from declaring a prototype for it, and must accept at least the two forms:
int main(int argc, char **argv);
int main(void);
or their equivalents. It may accept other forms too; see What's the use of the third environment variable in the C main()
? for one common form. In C, but not C++, a standard compiler can document other return types — and Microsoft has documented void
as a valid return type from VS 2008 onwards.
Because there is no implementation-provided prototype for main()
, the compiler can't officially reject any declarations/definitions of main()
, though it might pass comment on forms it doesn't recognize (GCC does comment on main()
functions that do not return an int
type, for example).
Related videos on Youtube
Comments
-
gangadhars over 1 year
Recently I got a question when writing a program for file opening.
Let me explain my question clearly. Here I'm taking
open
call as an example.To create a file:
open("file_name", O_CREAT, 0766); //passing 3 parametrs
To open a file:
open("file_name", O_RDWR); //only 2 arguments.
Then I clearly observed this point and it also works for
main()
too.main(void) //worked main(int argc, char **argv); //worked main(int argc) //worked and it's doesn't give an error like "too few arguments". main() //worked
So how we can create these optional arguments? How exactly can the compiler validate these prototypes? If possible, please write an example program.
-
gangadhars over 10 yearsbut how can they validate these. its not giving any argument like "too few arguments".
-
Kerrek SB over 10 years@SGG: The same way that
printf
can validate whether you've passed the correct number and type of arguments. -
gangadhars over 10 years@KerrekSB: sorry, i'm missing clarity. See there is a function which takes one argument or nothing(void). I mean, function should be validate if i call function() or function(10). Can you write the definition for that function.
-
Kerrek SB over 10 years@SGG: You cannot. You have to document your contract and rely on the user sticking to the contract. For that matter, you cannot have zero arguments, you must have at least one for varargs-style functions.
-
Jonathan Leffler over 10 yearsComment: you could move all the
va_list
code inside the condition; it is only needed there. You don't have to useva_start()
in a varargs function, even though you must use it before you can access any of the variable arguments (and when you do use it, you must callva_end()
too). -
Jonathan Leffler over 10 yearsHmmm...the standard uses the name
oflags
for what you calledmode
, and the third argument is amode_t
argument for the 'mode' (permissions) on the file. Just an FYI. -
Keith Thompson over 10 yearsThe
open
function predates the, ...
syntax that was introduced by the 1989 ANSI C standard. Early versions ofopen
simply documented the two different forms, and depend on weak type checking to permit both of them (in the absence of prototypes, the compiler won't diagnose calls with the wrong number of arguments, and prototypes weren't introduced until 1989). With the introduction of the ANSI C standard, the definition ofopen
was updated to use, ...
(and presumably to use<stdarg.h>
internally). -
Keith Thompson over 10 yearsActually a compiler can reject forms of
main
that it doesn't accept. Alternate forms are implementation-defined, meaning that the compiler must be accompanied by a document that lists them. A program with a definition that's neither one of the two standard forms nor an implementation-defined form for the current compiler has undefined behavior (by omission, since the standard doesn't define the behavior) (5.1.2.2.1). Rejecting a translation unit is an acceptable response to undefined behavior (3.4.3).