Search code examples
cfunctionreturn

C function not returning value


I've written a program for a class and am having a problem. The purpose of the program is to read a set of values into an array, calculate the average, and then find how many elements in that array are larger than that average. The function prototypes were provided so that cannot be changed. Also, we were instructed to initialize the array to size 10 and double the size whenever the number of read elements exceeds the current size, so that cannot be changed.

The problem I'm running into is returning a value from the aboveaverage function. It works properly within itself (I can put a printf to display count before return, but in the main function, the value being returned is 0. Is there anyone that can help with this please? It's getting frustrating.

Also, the commented printf line was to check the value being returned by the function. I commented it out instead of deleting it so I wouldn't have to retype it every time.

#include <stdio.h>
#include <stdlib.h>

double average(double *ptr, int size);
int aboveaverage(double *ptr, int size, double average);

int main(int argc, char* argv[])
{
    double *ptr, avg, above, temp;
    int size = 10, i, j;
    void *tmp;
    FILE *fp;

    avg = above = 0;

    if (argc != 2)
    {
        printf("Invalid number of arguments, 2 required\n");
        return 1;
    }

    fp = fopen(argv[1], "r");
    ptr = (double *)calloc(10, sizeof(double));
    printf("Allocated 10 doubles\n");

    for (i = 0;fscanf(fp, "%lf", &temp) != EOF; i++)
    {
        if (i >= size - 1)
        {
            size*=2;    
            tmp = realloc(ptr, size);
            if (tmp == NULL)
            {
                printf("Error with realloc, exiting\n");
                return 1;
            }
            printf("Reallocated to %d doubles\n", size);
        }
        ptr[i] = temp;
        j = i;
    }

    size = j + 1;
    avg = average(ptr, size);
    above = aboveaverage(ptr, size, avg);
    //printf("%d\n", above);

    printf("%d elements are above average of %lf\n", above, avg);

    free(ptr);

    return 0; 
}

double average(double *ptr, int size)
{
    double sum;
    int i;
    while (i < size)
    {
        sum+=ptr[i];
        i++;
    }

    return (sum / size);
}

int aboveaverage(double *ptr, int size, double avg)
{
    int count=0, temp;
    for (int i = 0; i < size; i++)
    {
        temp = (int)ptr[i];
        if (temp > avg)
        count++;
    }
    return count;
}

Solution

  • So other answers have already pointed out where the problem is and how exactly can it be fixed.

    printf("%d elements are above average of %lf\n", above, avg); 
    

    You pass %d as the format string and then you pass a double.

    This can be fixed by declaring above as int (since that is what your function returns too).

    But I would like to add as to why it is wrong and why are you getting a zero.

    So this is the issue with var args functions. Since the prototype says nothing about the types of the arguments, you call to printf assumes that the second argument is of type double.

    Now the calling convention says that the second argument (if it is float or double) should be passed in the SSE register (on windows in the XMM1 register). But since the printf function sees that the format string is %d so it expects for the second argument to be int. Now int arguments are passed in the general purpose registers (on windows second is passed in rdx).

    As a result it gets a garbage value.

    I hope this helps you better understand the problem.