gangadhars
gangadhars

Reputation: 2728

How can I make a function with optional arguments in C?

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.

Upvotes: 6

Views: 21790

Answers (2)

Kerrek SB
Kerrek SB

Reputation: 477150

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

Upvotes: 7

Jonathan Leffler
Jonathan Leffler

Reputation: 754130

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

Upvotes: 1

Related Questions