5

I'm new to C++ programming and I'm trying to get the size of an array. Can anybody explain me why this happens? I've tried running the code in runnable.com and the same result shows.

I'm sure this is not the right way to do it. If possible, can you suggest any EASY way to get the size of that kind of array?

#include <iostream>

using namespace std;

int main ()
{
  int set1[] = {1, 9, 3, 50, 31, 65};
  int set234[] = {3, 5, 5};

  cout << sizeof(set1) << endl;
  cout << sizeof(set234) << endl;

  cout << "When sizeof() return value is divided by 4"<< endl;
  cout << sizeof(set1) / 4 << endl; 
  cout << sizeof(set234) / 4 << endl;

  return 0;
}

****************************************************************
Output:
24
12
When sizeof() return value is divided by 4
6
3
****************************************************************

**EDIT : Thank you for your responses. flies away :D

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
NOWA
  • 53
  • 3

6 Answers6

4

The size of an array is equal to the sum of sizes of all its elements. As in your example you deal with arrays of type int then it seems sizeof( int ) in your system is equal to 4, So as the first array has 6 elements then its size is equal to 6 * sizeof( int )that is 24. The size of the second array is equal to 3 * sizeof( int )that is 12. If for example sizeof( int ) in your system would be equal to 8 then the size of the first array would be equal to 48 ( 6 * sizeof* int ) ) and the size of the second array would be equal to 24 ( 3 * sizeof( int ) ).

So if you want for example to know how many elements there are in an array you can calculate this the following way

sizeof( YouArray ) / sizeof( YourArray[0] )

or

sizeof( YouArray ) / sizeof( ElementType )
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 1
    +1 or `sizeof(YourArray)/sizeof(*YourArray)`, and all of which (debatably unhelpfully), compile when `YourArray` is a simple pointer rather than a genuine native array. More fuel to the fire of using `std:array<>` if offered by one's toolchain. – WhozCraig Sep 02 '14 at 17:45
  • @NOWA this solution is somewhat dangerous, as if `YouArray` is actually a pointer or something with an overloaded `[]`, it returns spurious information with no warning. – Yakk - Adam Nevraumont Sep 02 '14 at 18:46
  • @Yakk In this case you may use standard class std::extent – Vlad from Moscow Sep 02 '14 at 18:58
1

sizeof returns the number of bytes, not the number of elements. Mostly you should avoid arrays; use std::vector or std::array, both provide an easy way to get the number of elements.

Alan Stokes
  • 18,815
  • 3
  • 45
  • 64
0

sizeof returns the size of the array in bytes, not elements. It looks like you're running on a 32-bit system (or LP64, meaning only longs and pointers are 64-bit, but ints are still 32), so each element in your integer array is 4 bytes. In your set1, which is 6 elements, that is 6x4=24 bytes.

To get the size in elements, do sizeof(set1)/sizeof(set1[0]). Not however, that works for arrays where you've listed the elements at compile time. If, however, you just have an int*, the sizeof operator will return the size of the pointer.

Doug Richardson
  • 10,483
  • 6
  • 51
  • 77
0

sizeof() gives you the total size in bytes. For example, if int is 4, and you have 6 elements in array. It'll return 4*6=24 as the answer. Thus the following code will give you the size of an array .

#include <iostream>

using namespace std;

int main ()
{
  int set1[] = {1, 9, 3, 50, 31, 65};
  int set234[] = {3, 5, 5};

  cout << (sizeof(set1))/4 << endl;
  cout << (sizeof(set234))/4 << endl;


  return 0;
}

You can also use this :

#include <iostream>
#include <array>

int main ()
{
  array<int,5> a;
  cout << "size is" << a.size();
return 0;
}
saruftw
  • 1,104
  • 2
  • 14
  • 37
0

To get the count of elements in an array allocated on the stack, the usual technique is to get the total size, in bytes, of the whole array, and then divide that by the size, in bytes, of a single array item:

<item count> = <total array size in bytes> / <single array item size in bytes>

However, this formula can be applied only to arrays allocated on the stack, not to arrays dynamically allocated on the heap (e.g. using new[]): in this latter case, you need to keep the array item count as a separate piece of information.

Microsoft Visual C++ provides a convenient _countof() macro, that does the above calculation for you, and safely breaks the compilation process if the argument is a pointer e.g. to a dynamically allocated array (since in that case the above formula gives an incorrect result, i.e. the size of a pointer - which is fixed, e.g. 4 bytes on 32-bit systems, and unrelated to the pointed-to array size - divided by the size of the first pointed item).

It seems there is an equivalent safe ARRAY_SIZE() macro for Linux.

Community
  • 1
  • 1
Mr.C64
  • 41,637
  • 14
  • 86
  • 162
0
#include <cstddef>

template<class T, std::size_t N>
std::size_t length_of( T(&)[N] ) {
  return N;
}

is a template that solves your problem.

A more industrial-strength version in C++11 is:

#include <array>

template<class T, std::size_t N>
constexpr std::size_t size( T(&)[N] ) {
  return N;
}
template<class T, std::size_t N>
constexpr std::size_t size( std::array<T,N> const& ) {
  return N;
}
template<class C,class=void>
struct has_size : std::false_type {};
template<class>using void_t=void;
template<class C, void_t< decltype( std::declval<C&>().size() ) > >
struct has_size : std::true_type {};

template<bool b, class T=void>using enable_if_t=typename std::enable_if<b,T>::type;

template<class C, class=enable_if_t< has_size<C>::value, bool[1] >>
constexpr std::size_t size( C const& c ) {
  return c.size();
}

template<class C, class=enable_if_t< !has_size<C>::value, bool[2] >>
constexpr std::size_t size( C const& c ) {
  using std::begin; using std::end;
  return end(c)-begin(c);
}

which probably goes too far. Note that non-random access iterators in containers that lack a size will probably fail to compile (as - is usually not defined), which is sort of on purpoes (we don't want to accidentally do O(n) work).

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • I'd just call it size. An alternative version (which would work for all containers, not just C style arrays) would be to use `return std::end( array ) - std::begin( array );` (where `array` is the name of your argument). Why the standard provided `std::begin` and `std::end` without providing `std::size` beats me. – James Kanze Sep 02 '14 at 19:11
  • @JamesKanze intimidating industrial strength version added. Using `begin`/`end` when there is a `size` is also a bad idea, imho, because it may be far less efficient and/or not work (see `std::unordered_map`, which has a `size()` but no `operator-` on its iterators) The `std::array` version above may be redundant, as I think `.size()` is already `constexpr` for `array`? – Yakk - Adam Nevraumont Sep 02 '14 at 19:31
  • You're right, of course, that if the container has `size`, that's what you should use. But my real question remains: why isn't it in the standard? As your code points out, an industrial strength version isn't trivial, and it's really something that the standard should provide. – James Kanze Sep 04 '14 at 12:53
  • @jameskanze for one, you did not put it in there. For two, it will be easiet post-concepts. For three, should it work on containers with no `size` and no random access iterators? That implies it being slow. How should it fail? Early? Should it duck type or use traits to fail? Should we have a slow size and fast size? – Yakk - Adam Nevraumont Sep 04 '14 at 13:04
  • I didn't put in `std::begin` and `std::end` either; I did frequently post that anyone using C++ should have them in their toolkit (but I did that for `size` as well). For the rest, having `size` is a standard requirement for STL compatible containers: what happens with `std::begin` for a user defined container which doesn't support iterators? (I'm not sure, but I think the basic rule is that the function is overloaded for C style arrays, and otherwise forwards to the corresponding function on the container. Which will fail to compile if the function doesn't exist.) – James Kanze Sep 04 '14 at 17:36
  • @jameskanze `std::begin` and `std::end` and ADL based lookup of `begin` and `end` where basically required for `for(:)` ranged-based loops to work on arrays and non-standard containers without modifying said containers. So they where added as part of that effort. No such need for `std::size` existed. – Yakk - Adam Nevraumont Sep 04 '14 at 17:45