Finding size of an array using Try-Catch Blocks Problem

Hi Guys
I am trying to find the size of an array using a Try-Catch block. As seen on the code, I want the error to be caught when the index is out of range in "while" loop but at each time, program stops working. Can You please help me with this ?
Thanks in advance. (I tried this method on C#.Net, it worked)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int x[] = {34,5,1,536,2};
int length = 0;
int tt = 0;
    try
    {
         while(true)
         {
               tt = x[length];
               length++;     
         }
    }
    catch(...)
    {
         cout << length << endl;
    }
1
2
int x[] = {34,5,1,536,2};
int length = sizeof(x)/sizeof(x[0]);


Don't play with exceptions.

EDIT: Fixed.
Last edited on
C++ does not have built-in bounds checking like C# does. When you step out of bounds of your array, you will just start accessing random memory.

Regardless... this is a terrible way to find the size of an array (even in C#). Not only is it slow because you have to iterate over the entire array... but it also forces an error which is entirely unnecessary.

C# has Length properties for all its containers that you can check. C++ has them for its container classes (like vector, etc) that you can use... but not for raw arrays.

For raw arrays you can use this array_size function:

1
2
3
4
5
6
7
8
9
10
template <typename T, unsigned S>
inline unsigned array_size( const T (&v)[S] ) { return S; }


int main()
{
    int x[] = {34,5,1,536,2};

    cout << array_size(x);
};



Note: array_size only works with fixed size arrays. It does not work with dynamic arrays, or pointers. You cannot obtain the size of a dynamic array/pointer from just the pointer... the size has to be tracked separately.


EDIT:

EssGeEich's sizeof approach to get the array size will also work... but is more error prone because it will give false results for pointers, whereas array_size will generate a compiler error.
Last edited on
Thank You for You all but I couldn't understand the method what You did here

1
2
template <typename T, unsigned S>
inline unsigned array_size( const T (&v)[S] ) { return S; }


which topics should I study ?"Templates" ?
Disch's suggested approach is reliant on templates. The T (&v)[S] parameter is a reference to an array of type T and size S called v. As T and S are templated a version of array_size will be instantiated with the required values of T and S, which gives you the size (it's just the resultant value of S.)

Andy

PS Note that there is a limitation to Disch's approach over the more "stupid" (and standard in C programming) approach EssGeEich mentions (sizeof(x)/sizeof(x[0]);)

This code snippet fails to compile with Disch's approach (but is ok with EssGeEich's) as it can't handle a calculation inside the square brackets.

1
2
3
int foo[] = {1, 2, 3, 4};

int bar[2 * countof(foo)] = {0};


There is a way to get the security of Disch approach but have it compile; I went on about it before here:

C++ ARRAY_SIZE() - why you still need a macro
http://www.cplusplus.com/forum/general/103284/

My post includes a link to a more authorative blog entry explaining things in more detail.

Andy
Last edited on
The thing is... passing arrays to functions "normally" will pass them as a pointer. IE:

1
2
3
4
5
6
7
8
void foo(int X[])
{
    // here, X is not an array, it's a pointer.
    // same as if it were declared as:
    //  void foo(int* X)
    //
    // You can't get the array size from a pointer.
}


If you want to pass an array by reference, you do the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void byref(int (&x)[15])
{
    // here, x is an array of 15 ints
}

void byptr(int x[15])
{
    // here, the '15' is pointless because x is a pointer to
    //   any number of elements
}

//============

int main()
{
    // passing by ref differs because the array size is preserved:
    int a[15];
    byref(a);  // OK
    byptr(a);  // OK

    int b[10];
    byref(b);  // COMPILER ERROR because int[10] is not int[15]
    byptr(b);  // OK because it's passed by pointer, and the size is lost
}



So the lesson here is... passing an array by reference will preserve the size. With that, we can pass the size as a template parameter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<unsigned S>
unsigned array_size( const int (&v)[S] )
{
    // here... 'v' is an array of size S.  So to get the size.. just return S
    return S;
}

int main()
{
    int a[3];
    unsigned size = array_size<3>(a);  // <- passes with S=3

    // but of course the compiler can determine the array size and fill in 'S'
    //   automatically:
    size = array_size(a);  // <- compiler automatically plugs in S=3
}


From there... we just need to template the type... since we might not always have an array of ints... we might have an array of floats or whatever. And that's how you get this:

1
2
template <typename T, unsigned S>
inline unsigned array_size( const T (&v)[S] ) { return S; }
Wow! Two great explanations. Thank You for your detailed explanation Disch and I can say that I am really impressed by your method andywestken. I gained more solutions to my problem than I expected :)
Topic archived. No new replies allowed.