Странный вывод итерации переменных va_list - PullRequest
0 голосов
/ 22 марта 2019

Я хочу написать функцию с неизвестными целочисленными членами и печатать только неотрицательные из них.Точнее, это примеры моих фраворитных выводов:

print_nonnegatives(1, 3, -4, 5, 6) = 1, 3, 5, 6
print_nonnegatives(-1) = 
print_nonnegatives(7, -1, -4, 9) = 7, 9

Итак, моя первая попытка:

#include <stdio.h>
#include <stdarg.h>
#include <math.h>
#define BIG_INT 100
void print_nonnegatives(int arg1, ...)
{
    va_list ap;
    va_start(ap, arg1);
    for (int i = arg1; -BIG_INT < i && i < BIG_INT; i = va_arg(ap, int))
    {
        if (i >= 0)
        {
            printf("%d ", i);
        }
    }
    va_end(ap);
    puts("\n");
}

int main()
{
    print_nonnegatives(1, 3, -4, 5, 6);
    print_nonnegatives(-1);
    print_nonnegatives(7, -1, -1, 9);
}

Это работает;но есть несколько грязных линий.Например, если один из аргументов больше, чем BIG_INT, он будет потерян.Я пытался изменить условие -BIG_INT #include <stdio.h> #include <stdarg.h> #include <math.h> #define BIG_INT 100 void print_nonnegatives(int arg1, ...) { va_list ap; va_start(ap, arg1); for (int i = arg1; i / i == 1; i = va_arg(ap, int)) { if (i >= 0) { printf("%d ", i); } } va_end(ap); puts("\n"); } int main() { print_nonnegatives(1, 3, -4, 5, 6); //print_nonnegatives(-1); //print_nonnegatives(7, -1, -1, 9); } Примечательным фактом является то, что я компилирую с gcc в Linux.

Ответы [ 2 ]

0 голосов
/ 22 марта 2019

Вы должны сообщить своей функции, сколько целых чисел вы передаете ей - первый аргумент может сказать это. Кстати, это должен быть первый аргумент, поскольку при использовании соглашения о вызовах 'cdecl' первый аргумент имеет известное и фиксированное местоположение в кадре стека, поэтому вызываемый объект может использовать его, чтобы определить, сколько содержимого было помещено в стек в качестве аргументов. Вы можете сделать это так:

#include <cstdarg>
#include <iostream>

void print(int howMany, ...)
{
    va_list args;
    va_start(args, howMany);

    while(howMany--)
    {
        int nextNum = va_arg(args, int);
        if (nextNum > 0) std::cout << nextNum << std::endl;
    }

    va_end(args);
}


int main()
{
    print(9 /*tells how many ints follows*/, 10,-20,30,40,-50,60,-70,80,90);
}
0 голосов
/ 22 марта 2019

«Плохой вывод» происходит из-за того, что вы не передаете аргумент для завершения списка аргументов.

Функция va_arg не будет автоматически возвращать какой-то «конец списка аргументов»msgstr "Значение, когда вы достигнете конца списка аргументов, вместо этого он просто даст вам" следующий "аргумент в бесконечности.Это означает, что вы выйдете за пределы списка аргументов и получите неопределенное поведение .

. Вам нужно передать значение, большее или меньшее, чем BIG_INT, чтобы завершитьсписок аргументов (с показанным первым примером).

...