Search code examples
cstandard-library

How to solve this related to variable arguments in C using stdard.h library?


Consider the following code:

#include<stdio.h>
#include<stdarg.h>
int sum(int, ...);
int main()
{
    int a;
    a=sum(10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    printf("the sum is %d", a);
    return 0;
}

int sum(int a, ...)
{
    int s=0, i=1;
    va_list ls;
    va_start(ls, a);

    while(i<=a)
    {
        s=s+va_arg(ls, int);
        i++;
    }
    va_end(ls);
    return s;
}

The above code computes the sum of first 10 natural numbers, by using the variable arguments, by sum function. a the first argument of sum, it is specified that the user is giving 10 natural numbers whose sum is needed but I want some way so that we can find the sum without giving the count of the numbers I'm going to add. I means

 sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

will calculate the sum of the first 10 natural numbers which is 55. Please find a way and tell me


Solution

  • Your example is not a good use case for variadic arguments. You buy the flexibility of summing an arbitrary number of values at the cost of type safety. Your code must also rely on either specifying the number of arguments or on providing a sentinel value. (There are methods to check such things in static analysis, but they are compiler dependent.)

    But when do you need to sum arbitrary lists of values in C? In C, data is organised in arrays. So the C way to do what you want is:

    int array_sum(int a[], size_t n)
    {
        int sum = 0;
    
        while (n--) sum += a[n];        
        return sum;
    }
    

    If you want, you can turn this into a variadic function with a variadic macro that uses C99 compound literals and the countof macro, which determines the size of an array:

    #define SUM(...) array_sum((int[]){__VA_ARGS__}, \
        sizeof((int[]){__VA_ARGS__}) / sizeof((int[]){__VA_ARGS__}[0]))
    

    Now you can use both arrays and variadic lists:

    int a[] = {1, 2, 3, 4, 5, 6};
    
    printf("%d\n", array_sum(a, 6));
    printf("%d\n", SUM(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
    printf("%d\n", SUM(0xff, 1ull, 0.0));
    

    Note how the non-integers are converted to signed integers before summing with the usual rules. The <stdarg.h> approach will not work in this case, because the function relies on all parameters being ints, but it has no means of enforcing that.