tags:

views:

122

answers:

7

Hi.

PHP has a func_get_args() for getting all function arguments, and JavaScript has the functions object.

I've written a very simple max() in C

int max(int a, int b) {

    if (a > b) {
        return a;   
    } else {
        return b;
    }
}

I'm pretty sure in most languages you can supply any number of arguments to their max() (or equivalent) built in. Can you do this in C?

I thought this question may have been what I wanted, but I don't think it is.

Please keep in mind I'm still learning too. :)

Many thanks.

+5  A: 

Yes, C has the concept of variadic functions, which is similar to the way printf() allows a variable number of arguments.

A maximum function would look something like this:

#include <stdio.h>
#include <stdarg.h>
#include <limits.h>

static int myMax (int quant, ...) {
    va_list vlst;
    int i;
    int num;
    int max = INT_MIN;

    va_start (vlst, quant);

    for (i = 0; i < quant; i++) {
        if (i == 0) {
            max = va_arg (vlst, int);
        } else {
            num = va_arg (vlst, int);
            if (num > max) {
                max = num;
            }
        }
    }
    va_end (vlst);
    return max;
}

int main (void) {
    printf ("Maximum is %d\n", myMax (5, 97, 5, 22, 5, 6));
    printf ("Maximum is %d\n", myMax (0));
    return 0;
}

This outputs:

Maximum is 97
Maximum is -2147483648

Note the use of the quant variable. There are generally two ways to indicate the end of your arguments, either a count up front (the 5) or a sentinel value at the back.

An example of the latter would be a list of pointers, passing NULL as the last. Since this max function needs to be able to handle the entire range of integers, a sentinel solution is not viable.

The printf function uses the former approach but slightly differently. It doesn't have a specific count, rather it uses the % fields in the format string to figure out the other arguments.

paxdiablo
+2  A: 

here is a link to site that shows an example of using varargs in c Writing a ``varargs'' Function

You can use the va_args function to retrieve the optional arguments you pass to a function. And using this you can pass 0-n optional parameters. So you can support more then 2 arguments if you choose

Tristan
Note that unlike PHP and Javascript, with C varargs your function needs to be able to work out from the values of the non-variable args, what the types and number of the varargs are (or I guess you could work out the type of the first vararg from the non-var args, then the type of the second from the value of the first and so on). So you will not get a vararg `max` function that looks quite how you want it to look - this is a limitation of the C language.
Steve Jessop
+8  A: 

You could write a variable-arguments function that takes the number of arguments, for example

#include <stdio.h>
#include <stdarg.h>

int sum(int numArgs, ...)
{
    va_list args;
    va_start(args, numArgs);

    int ret = 0;

    for(unsigned int i = 0; i < numArgs; ++i)
    {
        ret += va_arg(args, int);
    }    

    va_end(args);

    return ret;
}    

int main()
{
    printf("%d\n", sum(4,  1,3,3,7)); /* prints 14 */
}

The function assumes that each variable argument is an integer (see va_arg call).

AndiDog
That's rather strange implementation of `max`... ;)
Dummy00001
Thanks, but `max()` is meant to return the largest number, not add them up :P
alex
Corrected that ^^. Implementing `max` should be pretty straightforward ;)
AndiDog
Do I *have* to tell the function how many arguments I'm sending? `printf()` doesn't seem to want to know, but I guess it could count all the format characters in the first argument to find out.
alex
That's right, printf just looks at the number of format codes. Put in too many format codes and it's likely to misbehave in interesting ways.
bdonlan
@AndiDog: You've still left it as a call to `max` instead of `sum` in the `printf` statement.
torak
@alex: Yes, you have to. But you could work around that using macros. For example, one could use a sentinel value INT_MIN that stops the function from going through the arguments. Then you could define a variadic macro (note that not all compilers support that) `#define max(...) maxfunction(__VA_ARGS__, INT_MIN)`.
AndiDog
@AndiDog: I'd expect `max(INT_MIN, 0)` to be well-defined. I can't really see how to safely pass a sentinel.
MSalters
+1  A: 

Yes, you can declare a variadic function in C. The most commonly used one is probably printf, which has a declaration that looks like the following

int printf(const char *format, ...);

The ... is how it declares that it accepts a variable number of arguments.

To access those argument it can uses va_start, va_arg and the like which are typically macros defined in stdarg.h. See here

It is probably also worth noting that you can often "confuse" such a function. For example the following call to printf will print whatever happens to be on the top of the stack when it is called. In reality this is probably the saved stack base pointer.

printf("%d");
torak
+2  A: 

In fact, this are two questions. First of all C99 only requires that a C implementation may handle at least:

  • 127 parameters in one function definition
  • 127 arguments in one function call

Now, to your real question, yes there are so-called variadic functions and macros in C99. The syntax for the declaration is with ... in the argument list. The implementation of variadic functions goes with macros from the stdarg.h header file.

Jens Gustedt
A: 

C can have functions receive an arbitrary number of parameters.

You already know one: printf()

printf("Hello World\n");
printf("%s\n", "Hello World");
printf("%d + %d is %d\n", 2, 2, 2+2);

There is no max function which accepts an arbitrary number of parameters, but it's a good exercise for you to write your own.

Use <stdarg.h> and the va_list, va_start, va_arg, and va_end identifiers defined in that header.

http://www.kernel.org/doc/man-pages/online/pages/man3/stdarg.3.html

pmg
+1  A: 

Another alternative is to pass in an array, like main(). for example:

int myfunc(type* argarray, int argcount);

tenfour