0

I have made a separate function display() for displaying the numbers and wanted to send the initialized argument pointer to this function.I am not getting the expected result. What is going wrong here? I am using gcc version 10.1.0 (GCC)

/* Expected OUTPUT */
99 + 68 -> Total = 167
11 + 79 + 32-> Total = 122
23 + 34 + 45 + 56 + 78 -> Total = 236 

/* Getting OUTPUT */
99 + 68 -> Total = 224
11 + 79 + 32 -> Total = 1410200528
23 + 34 + 45 + 56 + 78 -> Total = -1056735662


My code is :

/* Program in which the variable length list is passed to another function */
#include<stdio.h>
#include<stdarg.h>

int sum(int, ...);
void display(int,va_list);

int main(void)
{
    printf("\b\b-> Total = %d\n",sum(2,99,68));
    printf("\b\b-> Total = %d\n",sum(3,11,79,32));
    printf("\b\b-> Total = %d\n",sum(5,23,34,45,56,78));

    return 0;
}

int sum(int num, ...)
{
    int i;
    va_list ap;
    int arg,total = 0;
    va_start(ap,num);
    display(num,ap);

    for(i=0; i<num; i++)
    {
        arg=va_arg(ap,int);
        total+=arg;
    }

    va_end(ap);
    return total;
}

void display(int num,va_list ap)
{
    int i,argument;
    for(i=0; i<num; i++)
    {
        argument=va_arg(ap,int);
        printf("%d + ",argument);
    }
}
0

1 Answer 1

2

The rule is strict from C11 7.16p3:

The object ap [of type va_list] may be passed as an argument to another function; if that function invokes the va_arg macro with parameter ap, the value of ap in the calling function is indeterminate and shall be passed to the va_end macro prior to any further reference to ap.

The code:

display(num,ap);
va_arg(ap, ...);

is invalid - once you pass va_list to another function, you can only call va_end. You could take a pointer to va_list.

{
    ...
    display(num, &ap);
    va_arg(ap, int); // ok
    va_end(ap);
}
void display(int num, va_list *ap) {
    va_arg(*ap, int); // ok
}

But you are iterating va_list twice - once in display and once in sum. va_list remembers it's position, so to iterate the list twice you have to have two va_list initialized from the start. The simplest in your case is to initialize va_list twice. So you can do:

int sum(int num, ...) {
    va_list ap;
    va_start(ap, num);
    display(num, ap);
    va_end(ap);

    int total = 0;
    va_start(ap, num);
    for (int i = 0; i < num; i++) {
        int arg = va_arg(ap, int);
        total += arg;
    }
    va_end(ap);

    return total;
}

void display(int num, va_list ap)
{
    for(int i = 0; i < num; i++)
    {
        int argument = va_arg(ap,int);
        printf("%d + ",argument);
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Very nice solution and answer.
What difference does it make if I wrote int i; for(i=0; i<num; i++) instead of for(int i=0; i<num; i++) . Also for argument variable. I could have declared it before the for loop.
What difference does it make Technically: none.

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.