Home > database >  Why does this code report that -31 is greater than 6?
Why does this code report that -31 is greater than 6?

Time:06-24

I have a function double max(int count, ...) in my program. This function should return the highest number, but it reports that -31 > 6. Where is my mistake? I'm trying to learn va_. How can I fix this?

double max(int count, ...)
{
    double max = INT_MIN, test;

    int i;
    va_list values;
    va_start(values, count);
    for (i = 0; i < count;   i)
    {
        test = va_arg(values, double);
        if (test > max)
        {
            max = test;
        }
    }
    va_end(values);
    return max;
}

int main()
{
    printf("%ld", max(5, 1, 6, -31, 23, 24));
    return 0;
}

CodePudding user response:

You are invoking undefined behavior. You are not passing in double values to max(), you are passing in int values instead. int and double are different sizes in memory, and va_arg() can't read an int parameter as if it were a double, and vice versa. You need to match the types correctly.

In this example, change all of the doubles to ints, eg:

int max(int count, ...)
{
    int max = INT_MIN, test;

    va_list values;
    va_start(values, count);
    for(int i = 0; i < count;   i)
    {
        test = va_arg(values, int);
        if(test > max)
        {
            max = test;
        }
    }
    va_end(values);
    return max;
}

int main()
{
    printf("%d", max(5,1,6,-31,23,24));
    return 0;
}

Online Demo

Otherwise, change the ints to doubles instead, eg:

double max(int count, ...)
{
    double max = -DBL_MAX, test;

    va_list values;
    va_start(values, count);
    for(int i = 0; i < count;   i)
    {
        test = va_arg(values, double);
        if(test > max)
        {
            max = test;
        }
    }
    va_end(values);
    return max;
}

int main()
{
    printf("%lf", max(5,1.0,6.0,-31.0,23.0,24.0));
    return 0;
}

Online Demo


Either way, you might consider a slight change in logic in how you are handling the max value. You should initialize it to the 1st value that is passed in, eg:

<type> max(int count, ...)
{
    if (count <= 0)
        return <default value>;

    va_list values;
    va_start(values, count);

    <type> max = va_arg(values, <type>), test;

    for(int i = 1; i < count;   i)
    {
        test = va_arg(values, <type>);
        if (test > max)
        {
            max = test;
        }
    }

    va_end(values);
    return max;
}

Also, note that all of the above is the C way of handling things. But you also tagged your question as C , and the C way to handle this would be to use a variadic template instead of ellipses (ie, no va_arg() needed), or else take a std::initializer_list or at least a pair of iterators so that you can then make use of the standard std::max_element() algorithm.

  •  Tags:  
  • c c
  • Related