sizeof(array) returns different values in main() and user defined functions

Hello, everyone. I found sizeof(array) only works correctly in main() function.
Could you please tell me why?

-------------------------------------------------
#include <iostream>
using namespace std;

void f(const int array[]){
cout << sizeof(array) << endl;
//cout << array[index] << endl; //1
}

int main(){
int array[5] = {3,4,9,1,5};
cout << sizeof(array) << endl;
f(array);
return 0;
}

The output is:
20
4
------------------------------------------------
but if I print the whole array in f() (remove comment at 1),
the array content can be still printed out.

Can anyone explain the reason behind it?

Thank you very much.
Last edited on
In main, array is of type int[5].

In f, array is of type const int*.

sizeof is a keyword that evaluates to the size of its "parameter".
The size of an array of 5 ints is 5 times the size of an int.
the size of a pointer (to a constant integer) is 4 (assuming 32-bit
platform).
A good reason to never pass an array to a function this way. However, you could try:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;

template <int SIZE>
void f(const int (&array)[SIZE])
{
   cout << sizeof(array) << endl;
}

int main()
{
   int array[5] = {3,4,9,1,5};
   cout << sizeof(array) << endl;
   f(array);
   return 0;
}
Or just use a vector as Bjarne intended. It has a size() method.
Thank you all!
You've provided a very good explanation. :-)
I'd like to add that you're never going to get the right size (actually, you are, but you're not going to get what you want) for an array with sizeof() unless each element of that array happens to be 1 byte wide (i.e. it's a char array and you're on x86 (i.e.e. very specific conditions)) (essentially; what jsmith said).

If you want it to work for arrays of all types:
#define SIZEOF_ARRAY(array) (sizeof(array) / sizeof(*array))
but again, that will only work in the function that created the variable, because only in that function can the compiler know the boundaries of an array (I think).
It will work as long as the compiler "knows" the real type of the array, which includes its size.

The template method is truly the best approach (generalized:)

1
2
3
4
5
6
7
8
9
10
// Some compilers balk at defining both of these methods;
template< typename T, size_t N >
size_t ArraySize( T (&)[ N ] )
    { return N; }

// This is the right one, but some compilers (gcc) cannot match
// this function correctly due to the constness:
template< typename T, size_t N >
size_t ArraySize( T (const &)[ N ] )
    { return N; }


The reason why this is preferred over

 
#define SIZEOF_ARRAY( blah ) ( sizeof( array ) / sizeof( *array ) ) 


Is that the former will ONLY compile for fixed-length array types, whereas
the latter will compile but generate the wrong answer for a variety of things:

1
2
3
4
5
6
7
8
9
10
11
int* pInt = 0;
int* intArray = new int[ 10 ];
int* pIntArray = intArray;
int   fixedLenArray[ 10 ];
int* pFixedLenArray = fixedLenArray;

SIZEOF_ARRAY( pInt );    // Compiles, outputs 1 (wrong, pInt is NULL, should be 0)
SIZEOF_ARRAY( intArray );  // Compiles, outputs 1 (wrong)
SIZEOF_ARRAY( pIntArray );  // Compiles, outputs 1 (wrong)
SIZEOF_ARRAY( fixedLenArray );  // Compiles, outputs 10 (correct)
SIZEOF_ARRAY( pFixedLenArray );  // Compiles, outputs 1 (wrong) 
Last edited on
You know, I found that macro-function-thing in the Linux kernel source code. I was already using it before then, but it was in there, too.

Maybe you should tell Linus about your templates... :3

Anyway, on a serious note, thanks for that. I knew it would only work for arrays like int array[10];, but will it work for arrays passed as parameters? My guess is no...

Also,
#define SIZEOF_ARRAY( blah ) ( sizeof( array ) / sizeof( *array ) )
1
2
// This is the right one, but some compilers (gcc) cannot match
// this function correctly due to the constness: 


?

This works fine in GCC:

1
2
3
template< typename T, size_t N >
size_t ArraySize( const T (&)[ N ] )
    { return N; }
Topic archived. No new replies allowed.