Search code examples
arrayscmaxsizeoffunction-definition

Program does not find highest number in array as intended


In the example below in the function "Highest Number" it takes a pointer to an integer and sorts through the array until it finds the highest number ranging from the sentinel value INT_MIN, to the biggest number in the array. However, using the "sizeof" function on pointers passed as function parameters does not seem to work. How can I properly find the highest number in the array given the array is passed to the function "Highest Number" through a parameter.

#include <stdio.h>
#include <stdlib.h>
int HighestNumber(int* array)
{
    int highest = INT_MIN;
    for(size_t x = 0; x < sizeof(array) / sizeof(array[0]); x++)
        if(array[x] > highest)
            highest = array[x];
    return highest;
}
int main()
{
    int *array = (int*)malloc(4*sizeof(int));
    array[0] = 66;
    array[1] = 552;
    array[2] = -17;
    array[3] = 1000;
    printf("%d", HighestNumber(array));
    return 0;
}

Solution

  • The sizeof trick doesn't work on pointers!

    If applied to pointers you get the (truncated) ratio between the size of a pointer, which is always the same, no matter how large your array is, and the size of a single element in that array, so in your case with int* most likely either 2 (64-bit system, typically 8-byte pointers, 4-byte int) or 1 (32-bit system, typically 4-byte pointers, 4-byte int), though other systems can yield yet other values, but still not the required one (apart from accidentally matching array size...).

    To use sizes on array you need to pass it explicitly by another parameter:

    int highestNumber(size_t length, int* array)
    {
        int highest = INT_MIN;
        while(length--)
        {
            if(*array > highest)
            {
               highest = *array;
            }
            ++array;
        }
        return highest;
    }
    

    while you can then apply the sizeof trick on the array being passed to:

    int array[4];
    // assign values to
    
    // array has not yet decayed to pointer, thus you can do:
    int highest = highestNumber(sizeof(array)/sizeof(*array), array);
    

    However in your example you use a dynamically allocated array – these only can be assigned to pointers, thus there's no way around tracking the size explicitly:

    size_t length = 4;
    int* array = malloc(length * sizeof(*array));
    // assign values
    int highest = highestNumber(length, array);
    

    Final note: You might as well use the length/size as second parameter, of course; having it as first would allow for:

    int highestNumber(size_t length, int array[length]);
    

    which is fully equivalent, as for the outermost dimension an explicitly specified array size is ignored and the parameter still remains a pointer (note that this does not apply for further dimensions), but this declaration expresses more explicitly what the function actually expects as arguments.

    Edit (stealing from Vlad from Moscow's answer):

    As you do not (intend to) modify the array within the function it is a good choice to accept a pointer to const – this allows to use both non-const and const arrays while the original function signature excludes the latter without need:

    int highestNumber(size_t length, int const* array)
    int highestNumber(size_t length, int const array[length]);