4

I've the following C++ array:

byte data[] = {0xc7, 0x05, 0x04, 0x11 ,0x45, 0x00, 0x00, 0x00, 0x00, 0x00};

How can I know how many items there are in this array?

Alon Gubkin
  • 56,458
  • 54
  • 195
  • 288

3 Answers3

10

For byte-sized elements, you can use sizeof(data).

More generally, sizeof(data)/sizeof(data[0]) will give the number of elements.


Since this issue came up in your last question, I'll clarify that this can't be used when you pass an array to a function as a parameter:

void f(byte arr[])
{
    //This always prints the size of a pointer, regardless of number of elements.
    cout << sizeof(arr);
}

void g()
{
    byte data[] = {0xc7, 0x05, 0x04, 0x11 ,0x45, 0x00, 0x00, 0x00, 0x00, 0x00};
    cout << sizeof(data);    //prints 10
}
interjay
  • 107,303
  • 21
  • 270
  • 254
  • 1
    Note that this will only work when the array definition is being seen by the compiler (that is either the array is global or within the same function). It will fail if the array is passed as argument to a function, and it will fail silently providing an erroneous answer. `int f( char data[] ) { return sizeof(data)/sizeof(data[0]); } void caller() { char array[] = { 0 }; f(array) }` will return the size of a pointer (usually 4/8) and not 1, which is the actual solution. This is because arrays decay into pointers at function calls when passed by value. – David Rodríguez - dribeas Jan 16 '10 at 11:11
  • Tip: it's common to define a macro like this: #define ARRSIZE(arr) (sizeof(arr)/sizeof(*(arr))) to get the number of elements of an array whose size is known at compile time. – Matteo Italia Jan 16 '10 at 11:13
  • "this can't be used when you pass an array to a function" ... It can when using references. – Georg Fritzsche Jan 16 '10 at 11:16
5

You should really use Neil's suggestion: std::vector<byte> is a much better solution in most cases (the only more complex part is initialization, on anything else it is safer).

If not, instead of using the sizeof(array)/sizeof(array[0]), or sizeof(array) (since sizeof(byte)==1), you can use a typesafe approach with templates:

template <typename T, unsigned int N>
unsigned int size_of_array( T (&)[N] ) {
   return N;
}

Or, if you need a compile time constant (and at the same time you want to make sure you do not accidentally call it on non-arrays:

template <typename T, unsigned int N>
char (&static_size_of_array( T (&)[N] ))[N];

#define compile_time_size(x) (sizeof(static_size_of_array((x))))

In most cases you will not need that last solution. Both templated solutions will fail fast when a pointer is passed (instead of an array):

void f( char array[] ) // misleading name:
{
   char array2[] = { 1, 2, 3 };
   size_of_array(array2);          // 3
   size_of_array(array);           // compile time error

   sizeof(array)/sizeof(array[0]); // 4/8, depending on architecture!!!
}
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
2
sizeof( data);     // because sizeof(byte) is 1

However, this is not a good general solution - particularly if you pass the array to functions:

void  f( byte a[] ) {
   // number of elements in 'a' unknown here 
}

The array decays to a pointer, so the sizeof operator will always give you the size of the pointer, not the number of elements in the array.

Instead, you should use a std::vector<byte>, which has a size() member function.

  • "The array decays to a pointer" ... references fix that: `template void f(byte (&a)[n])` – Georg Fritzsche Jan 16 '10 at 11:15
  • So you have to provide the size as a compile time template parameter? –  Jan 16 '10 at 11:21
  • No, see e.g. here (self-plug, but fastest to find): http://stackoverflow.com/questions/1745942/c-template-parameter-in-array-dimension/1745963 ... with references the full array type is preserved. – Georg Fritzsche Jan 16 '10 at 11:48