Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reliably get size of C-style array?

Tags:

c++

arrays

c

size

How do I reliably get the size of a C-style array? The method often recommended seems to be to use sizeof, but it doesn't work in the foo function, where x is passed in:

#include <iostream>

void foo(int x[]) {
  std::cerr << (sizeof(x) / sizeof(int)); // 2  
}

int main(){
    int x[] = {1,2,3,4,5};
    std::cerr << (sizeof(x) / sizeof(int)); // 5                              
    foo(x);
    return 0;
}

Answers to this question recommend sizeof but they don't say that it (apparently?) doesn't work if you pass the array around. So, do I have to use a sentinel instead? (I don't think the users of my foo function can always be trusted to put a sentinel at the end. Of course, I could use std::vector, but then I don't get the nice shorthand syntax {1,2,3,4,5}.)

like image 209
Frank Avatar asked Mar 08 '10 20:03

Frank


3 Answers

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?

like image 57
Michael Burr Avatar answered Oct 22 '22 17:10

Michael Burr


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.

like image 37
Danilo Piazzalunga Avatar answered Oct 22 '22 15:10

Danilo Piazzalunga


Now, you can use C++11's extent and rank.

By example:

#include <iostream>
#include <type_traits>

int main()
{
  int a[][3] = {{1, 2, 3}, {4, 5, 6}};

  std::cout << "\nRank:           : " << std::rank<decltype(a)>::value;
  std::cout << "\nSize: [_here_][]: " << std::extent<decltype(a), 0>::value;
  std::cout << "\nSize: [][_here_]: " << std::extent<decltype(a), 1>::value;
  std::cout << "\nSize: [][]_here_: " << std::extent<decltype(a), 2>::value;
}

prints:

Rank:           : 2
Size: [_here_][]: 2
Size: [][_here_]: 3
Size: [][]_here_: 0
like image 23
Picaud Vincent Avatar answered Oct 22 '22 15:10

Picaud Vincent