Search code examples
cvariadic-functions

Strange output iterating va_list varibles


I want to write a function whose task is printing only nonnegative components of input vector.

So, my first attempt is:

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

It works; but there are some dirty lines. For example, if one of the arguments is bigger than BIG_INT, it will fail.

I tried to change the condition -BIG_INT < i && i < BIG_INT to escape from this failure. So, I replaced it by i / i == 1. My main problem is that what are strange outputs and from where they are coming from?

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

Solution

  • The "bad output" comes from the fact that you don't pass an argument to end the argument list.

    The va_arg function won't automatically return some kind of "end of argument list" value when you reach the end of the argument list, instead it will just give you the "next" argument in infinity. That means you will go beyond the end of the argument list and have undefined behavior.

    You need to pass a value larger or smaller than BIG_INT to end the argument list (with the first example shown).