Why sizeof(param_array) is the size of pointer?

Solution 1:

A special C rule says that for function parameters, array types are adjusted to pointer types. That means:

int length(int array[]);

is equivalent to

int length(int *array);

So when you compute the sizeof the array you are actually computing the size of the pointer.

(C99, 6.7.5.3p7) "A declaration of a parameter as "array of type" shall be adjusted to "qualified pointer to type", where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation."

Solution 2:

The array decays into a pointer when you pass it into a function.

Solution 3:

As the other answerers have noted, a function declared to take an array is compiled the same as if it took a pointer.

The most common way I've seen to do your length method is with a #define, but if you play tricks with templates, you can make your function work.

template <size_t _Size> inline int length(int(& array)[_Size])
{
    //return sizeof(array) / sizeof(int);
    return _Size;
};

int array[] = {1, 2, 3, 4};
printf("%d\n", length(array)); // print 4

With your array of length 4, this gets compiled as a method that takes an array of length 4, and returns a static 4. This also has the advantage that if you try to pass something that isn't an array, the compiler will give an error, whereas the #define method doesn't.

int* foo = array;
printf("%d\n", length(foo)); 
    // error C2784: 'int length(int (&)[_Size])' : could not deduce template
    //     argument for 'int (&)[_Size]' from 'int *'
    // test.cpp(56) : see declaration of 'length'

Solution 4:

In the main program, the compiler knows the length of the array. In the subroutine, it doesn't. In particular, in a subroutine, a parameter of type int[] is identical to a parameter of type int *. In the main program, on the other hand, array has type int[4]. (You can test this by trying to assign another value to array in side main. The compiler will complain.)

Solution 5:

If you want length to be aware of the true size of the passed in array, that information has to be passed in, as everyone says. But it is possible for it to receive a reference to the array with the information also built-in:

int length(int n, int (* array)[n])
{
     return sizeof(*array) / sizeof(int);
}

int main()
{
    int array[] = {1, 2, 3, 4};
    printf("%d\n", length(4, &array)); // print 1
    printf("%d\n", sizeof(array) / sizeof(int)); // print 4
}

I don't know what good that actually does you, though, since the size is already provided in the first place. But you see that the sizeof operator works as you wanted it to in this case.