Передача списка аргументов переменной длины в другую функцию - PullRequest
0 голосов
/ 03 августа 2020

Я сделал отдельную функцию display () для отображения чисел и хотел отправить инициализированный указатель аргумента на эту функцию. Я не получаю ожидаемого результата. Что здесь не так? Я использую g cc версию 10.1.0 (G CC)

/* 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


Мой код:

/* 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);
    }
}

1 Ответ

2 голосов
/ 03 августа 2020

Правило строго из C11 7.16p3 :

Объект ap [типа va_list] может быть передан в качестве аргумента другой функции; если эта функция вызывает макрос va_arg с параметром ap, значение ap в вызывающей функции не определено и должно быть передано в макрос va_end до любой дальнейшей ссылки на ap .

Код:

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

недействителен - как только вы передадите va_list другой функции, вы сможете только вызвать va_end. Вы можете взять указатель на 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
}

Но вы повторяете va_list дважды - один раз на дисплее и один раз в sum. va_list запоминает свою позицию, поэтому для повторения списка дважды вам нужно иметь два va_list, инициализированных с самого начала. Самый простой в вашем случае - дважды инициализировать va_list. Итак, вы можете сделать:

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