views:

806

answers:

6

Is it possible to determine the size of an array if it was passed to another function (size isn't passed)? The array is initialized like int array[] = { XXX } ..

I understand that it's not possible to do sizeof since it will return the size of the pointer .. Reason I ask is because I need to run a for loop inside the other function where the array is passed. I tried something like:

for( int i = 0; array[i] != NULL; i++) {
........
}

But I noticed that at the near end of the array, array[i] sometimes contain garbage values like 758433 which is not a value specified in the initialization of the array..

+7  A: 

Nope, it's not possible.

One workaround: place a special value at the last value of the array so you can recognize it.

tekBlues
... and get ready to debug the cases when someone places that special value in the middle of the array. In other words: don't do it. Like others said: wither use well-defined containers (e.g. STL) or pass the size of the array along with it as other parameter of the function
Rom
+3  A: 

If you can't pass the size, you do need a distinguishable sentinel value at the end (and you need to put it there yourself -- as you've found, you can't trust C++ to do it automagically for you!). There's no way to just have the called function magically divine the size, if that's not passed in and there is no explicit, reliable sentinel in use.

Alex Martelli
A: 

Can you try appending a null character \0 to the array and then send it? That way, you can just check for \0 in the loop.

Alan Haggai Alavi
+12  A: 

If it's within your control, use a STL container such as a vector or deque instead of an array.

Fred Larson
Agreed. If you don't know about vector, now is a great time to learn! It will make your life much easier.
rlbond
+11  A: 

The other answers overlook one feature of c++. You can pass arrays by reference, and use templates:

template <typename T, int N>
void func(T (&a) [N]) {
    for (int i = 0; i < N; ++i) a[i] = T(); // reset all elements
}

then you can do this:

int x[10];
func(x);

but note, this only works for arrays, not pointers.

However, as other answers have noted, using std::vector is a better choice.

Evan Teran
+1 This is a somewhat of a solution, but will create a different func() symbol for each different array size. That is, in different places the passed array has different sizes, the function will be instantiated that many times. This could be helpful though to insert the size of the array in a call to another function that has the real implementation and receives the size, probably flagging it as inline (not that the compiler must follow your rule...) template<typename T, size_t N> inline void wrapper( T ( } -- with func() being the real function.
David Rodríguez - dribeas
sure, the goal would be to make the function which operates on it small enough that it is likely to get inlined. I also like your wrapper idea.
Evan Teran
+5  A: 

One obvious solution is to use STL. If it's not a possibility, it's better to pass array length explicitly. I'm skeptical about use the sentinel value trick, for this particular case. It works better with arrays of pointers, because NULL is a good value for a sentinel. With array of integers, it's not that easy - you need to have a "magic" sentinel value, which is not good.

Side note: If your array is defined and initalized as

 int array[] = { X, Y, Z };

in the same scope as your loop, then

sizeof(array) will return it's real size in bytes, not the size of the pointer. You can get the array length as

sizeof(array) / sizeof(array[0])

However, in general case, if you get array as a pointer, you can't use this trick.

Igor Krivokon