How to reliably get size of C-style array?

In C array parameters in C are really just pointers so sizeof() won't work. You either need to pass in the size as another parameter or use a sentinel - whichever is most appropriate for your design.

Some other options:

Some other info:

  • for C++, instead of passing a raw array pointer, you might want to have the parameter use something that wraps the array in a class template that keeps track of the array size and provides methods to copy data into the array in a safe manner. Something like STLSoft's array_proxy template or Boost's boost::array might help. I've used an array_proxy template to nice effect before. Inside the function using the parameter, you get std::vector like operations, but the caller of the function can be using a simple C array. There's no copying of the array - the array_proxy template takes care of packaging the array pointer and the array's size nearly automatically.

  • a macro to use in C for determining the number of elements in an array (for when sizeof() might help - ie., you're not dealing with a simple pointer): Is there a standard function in C that would return the length of an array?


A common idiom mentioned in GNU Libstdc++ documentation is the lengthof function:

template<typename T, unsigned int sz>
inline unsigned int lengthof(T (&)[sz]) { return sz; }

You can use it as

int x[] = {1,2,3,4,5};
std::cerr << lengthof(x) << std::endl;

Warning: this will work only when the array has not decayed into a pointer.


You can either pass the size around, use a sentinel or even better use std::vector. Even though std::vector lacks initializer lists it is still easy to construct a vector with a set of elements (although not quite as nice)

static const int arr[] = {1,2,3,4,5};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );

The std::vector class also makes making mistakes far harder, which is worth its weight in gold. Another bonus is that all C++ should be familiar with it and most C++ applications should be using a std::vector rather than a raw C array.

As a quick note, C++0x adds Initializer lists

std::vector<int> v = {1, 2, 3, 4};

You can also use Boost.Assign to do the same thing although the syntax is a bit more convoluted.

std::vector<int> v = boost::assign::list_of(1)(2)(3)(4);

or

std::vector<int> v;
v += 1, 2, 3, 4;

Tags:

C++

C

Arrays

Size