1

How do I implement arbitrary number of arguments in my Max(int num, ...) with ONLY arguments that needs to be compared in C? I'm using va_list from the C library stdarg.h

I've read Variable number of arguments in C programmng, but sadly it seems that there aren't any answers that can help me. Since it is a post in 2018, I wonder if there is a solution to my problem after 4 years from then.

I'm using va_list from the C library stdarg.h to implement Max() . While looking for the maximal value, I have to use for loop to retrieve the arguments from the very first to the last. And that is where I get stuck.

My goal is to implement Max() with only arguments that needs to be compared their value. But I can't find a way to stop my for loop from executing after it reach to the last argument. The mostly seem solutions on the net for breaking the for loop are:

  1. Adding an additional argument that represent the amount of arguments that you are passing in, which tells the for loop to loop for that amount of times
  2. Passing in a number that the for loop's condition part becomes false -> break out of the loop (In my code below, I pass the argument -1 in as the last argument to my function. When the for loop sees that value, it knows it has arrived to the end of the argument)

But the above solutions both require an additional arguments, which I can't achieve my goal. So are there any solutions that can help me with my problem? Any response is appreciated :)

#include <stdio.h>
#include <stdarg.h> // this library is required for infinite number of arguments

int Max(int num, ...){
    va_list ap;
    int temp;
    va_start(ap,num);
    int maximum = num;
    for(temp = va_arg(ap,int); temp!= -1/*put condition here */; temp = va_arg(ap, int)){
        if(temp > maximum){
            maximum = temp;
        }
    }
    va_end(ap);
    return maximum;
}

int main(){
    int maximum;
    printf("the input vals are: 1 3 4 6 3 78 100\n");
    maximum = Max(1,3,4,6,3,78,100, -1);
    printf("maximum val: %d\n",maximum);
}
5
  • 3
    There's no way in C to get what you want. You either need an initial argument that says how many arguments there are, something like a printf format string, or use an end-of-list marker (like your -1). Commented Oct 29, 2022 at 6:16
  • As for your "problem", why is this a "problem"? What is the actual and underlying problem you're trying to solve, and why do you think removing the end-of-list sentinel will solve that problem? Commented Oct 29, 2022 at 6:17
  • No, sorry. You have exactly the right idea. See section 15 Variable Length Arguments in the C FAQ, (which seems to be down atm.) Commented Oct 29, 2022 at 6:20
  • 1
    @Someprogrammerdude, thanks for your response. And to replied to what you've asked, I am only trying to implement functions like min() and max() myself. To let my function available to access unfixed number of arguments, I find that there is something called variadic-function in C. This is when I find out that we always put an argument to show the end of the list, so I started to search if there are any solution that enable me to remove this additional argument which can make my max() and min() function looks prettier, and more straightforward to use. : ) Commented Oct 29, 2022 at 6:43
  • A variadic function doesn't know how many arguments it is getting unless you tell it somehow. Passing a sentinel argument at the end of the list is one option. Passing the number of arguments at the beginning of the list is another option. Doing nothing is not an option. Commented Oct 29, 2022 at 7:25

2 Answers 2

0

The C standard does not provide any way for a function to know how many arguments were passed or which is the last one. Such information must be provided by the programmer.

You can use preprocessing features to do this. We can define a macro that counts its arguments:

#define Max(...)    \
    Max(sizeof (int []) {__VA_ARGS__} / sizeof (int), __VA_ARGS__)

This creates a compound literal of type array of int initialized with the macro arguments. Then it calculates the number of arguments by dividing the size of the array by the size of one element. Then it passes this size and the arguments to the Max function. (Note that a macro is not replaced in its own replacement list, so the replacement of the Max macro can call the Max function without causing repeated replacement.)

Then the function must take the number of following arguments as its first argument:

int Max(size_t N, ...)
{
    //  Initialize "maximum seen so far" to identity element of max operation.
    int maximum = INT_MIN;

    va_list ap;
    va_start(ap, N);
    for (size_t i = 0; i < N; ++i)
    {
        int t = va_arg(ap, int);
        if (maximum < t)
            maximum = t;
    }
    va_end(ap);
    return maximum;
}

Note that the function definition must appear before the macro definition in the source code, so that replacement of the Max macro does not occur in the function definition.

At least one value must be given. The macro could be made to support zero arguments with some changes to it and the function.

Sign up to request clarification or add additional context in comments.

Comments

0

Add this line somewhere after the definition of Max:

#define Max(...) Max(__VA_ARGS__, -1)

It will add -1 at the end of the argument list, so you don't have to.

As a side note, -1 is not a good sentinel for a function like Max because -1 is just an integer, no better or worse than any other integer. What if I want to find Max(-5,32,8,-1,77,-11,141)? I will let you ponder possible solutions for this problem.

3 Comments

Thanks to your response, yeh I have notice it after that, so I've modified the value to -_INT_MAX_ -1. Trully a fantastic solution, thank you bro! :)
However, I guess we need to define two functions with different names. Or the code won't work. Thanks anyway
You can do that but it is not necessary. The code works as is. Try and see for yourself.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.