Función con error de tiempo de ejecución de argumentos variables

He escrito esta función para calcular el promedio de algunos flotadores. Pero tiene un error de tiempo de ejecución en la última línea de la función "promedio". ¿Cuál es el problema?

#include <stdarg.h>
#include <stdio.h>



float average(float first , ...)
{
    int count = 0;
    float sum = 0 , i = first;

    va_list marker;

    va_start(marker , first);
    while(i != -1)
    {
        sum += i;
        count++;
        i = va_arg(marker , float);
    }

    va_end(marker);
    return(sum ? (sum / count) : 0);
}


int main(int argc , char* argv[])
{
    float avg = average(12.0f , 34.0f);

    printf("The average is : %f\n" , avg);
    scanf("a\n");
}

preguntado el 03 de mayo de 12 a las 17:05

Por experiencia personal, descubrí que las funciones que tienen un número variable de argumentos causan más problemas de los que valen, especialmente si se usa C++, ya que hay mejores (en mi humilde opinión) formas de evitar esto. -

En particular usando -1 como un centinela tiene un diseño realmente malo, este podría ser un valor válido. Dado que se supone que todos sus parámetros tienen el mismo tipo, tanto C++ como C le ofrecen mejores alternativas para esto. -

4 Respuestas

La función se repite hasta que ve un -1, y la persona que llama no está proporcionando el -1.

La página del manual en mi caja promete "errores aleatorios":

va_arg()
   ...
   If  there  is  no  next argument, or if type is not compatible with the
   type of the actual next argument (as promoted according to the  default
   argument promotions), random errors will occur.

Tratar:

float avg = average(12.0f, 34.0f, -1f);

contestado el 03 de mayo de 12 a las 17:05

Olvidó finalizar la llamada con un -1, entonces tus while loop provoca un comportamiento indefinido porque intenta seguir recibiendo más argumentos de los que pasó. Debería ser:

float avg = average(12.0f, 34.0f, -1f);

También, trabaja para float Se promueven argumentos para double cuando se pasa a funciones variádicas, por lo que no puede usar float con va_arg. Deberías estar usando double para todo esto:

double average(double first, ...)
{
    int count = 0;
    double sum = 0, i = first;

    va_list marker;

    va_start(marker, first);
    while(i != -1)
    {
        sum += i;
        count++;
        i = va_arg(marker, double);
    }

    va_end(marker);

    return sum ? sum / count : 0;
}

double avg = average(12.0, 34.0, -1.0);

contestado el 03 de mayo de 12 a las 17:05

Funcionó. Pero, ¿hay alguna forma de no usar -1 en los argumentos pasados? - arman_aegit

@ Arman-aegit, la función necesita saber de alguna manera cuándo dejar de extraer argumentos (es decir, cuándo detener el while lazo). Entonces, debe dar un valor al final como lo está haciendo ahora, o hacer algo como agregar un primer argumento que proporcione la cantidad de argumentos que desea sumar. Entonces sería como double average(int count, ...) y podrías hacer double avg = average(3, 1.0, 2.0, 3.0);. Lamentablemente, no existe una forma automática de saber cuántos argumentos se aprobaron. - Seth Carnegie

¿No quieres pasar -1 como el último argumento para detener el bucle while?

Además, creo que los flotantes se convierten en dobles cuando se usan VA, por lo que cambiar el flotante a doble sería bueno...

contestado el 03 de mayo de 12 a las 17:05

El problema es que no tiene una terminación para su bucle while. usted está buscando -1 pero nunca pases -1. Tienes que llamar a tu average función como

float avg = average(12.0f ,34.0f, -1);

Hay un ejemplo de tiempo de ejecución de este ejemplo en va_arg, va_fin, va_inicio que muestra casi exactamente su código, pero usando int en lugar de float por los valores.

contestado el 03 de mayo de 12 a las 17:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.