Albus Dumbledore
Albus Dumbledore

Reputation: 12616

Element count of an array in C++

Let's say I have an array arr. When would the following not give the number of elements of the array: sizeof(arr) / sizeof(arr[0])?

I can thing of only one case: the array contains elements that are of different derived types of the type of the array.

Am I right and are there (I am almost positive there must be) other such cases?

Sorry for the trivial question, I am a Java dev and I am rather new to C++.

Thanks!

Upvotes: 33

Views: 170418

Answers (15)

developer68
developer68

Reputation: 129

struct DXGINames
{
    char name[64];
    int number;
};

DXGINames DXGINamesArray[] =
{
"DXGI_FORMAT_UNKNOWN", 0,
"DXGI_FORMAT_R32G32B32A32_TYPELESS", 1,
"DXGI_FORMAT_R32G32B32A32_FLOAT", 2,
"DXGI_FORMAT_R32G32B32A32_UINT", 3,
"DXGI_FORMAT_R32G32B32A32_SINT", 4,
"DXGI_FORMAT_R32G32B32_TYPELESS", 5,
"DXGI_FORMAT_R32G32B32_FLOAT", 6,
"DXGI_FORMAT_R32G32B32_UINT", 7,
"DXGI_FORMAT_R32G32B32_SINT", 8,
"DXGI_FORMAT_R16G16B16A16_TYPELESS", 9
};

m_DXGINames = DXGINamesArray;

int count = sizeof(DXGINamesArray) / sizeof(DXGINames);

OR

#define countArray(a, b) (sizeof(a) / sizeof(b))

int c = countArray(DXGINamesArray, DXGINames);

Upvotes: 0

AL MaMun
AL MaMun

Reputation: 63

Determine how many numbers are in your array.

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n[10]  ;

    int l = sizeof(n)/sizeof(n[0]);

    cout << l;

    return 0;
}

Upvotes: 0

Benjamin Buch
Benjamin Buch

Reputation: 6123

It will work if and only if arr is a C-Array (type[size]; except for function parameters!), a reference to a C-Array (type(&)[size]) or a pointer to a C-Array (type(*)[size]).

Note you should use std::size or std::ssize instead with current C++-Standards!

In C++17 you can use std::size:

int arr[] = {1, 2, 3};
auto count = std::size(arr); // type std::size_t, value == 3

In C++20 you can additionally get a signed value by using std::ssize:

int arr[] = {1, 2, 3};
auto count = std::ssize(arr); // type std::ptrdiff_t, value == 3

Also note that C++ unfortunately inherited from C that C-Arrays are never passed by value (deep copy) to functions.

void f(int a[3]);

is the same as

void f(int* a);

so you loose the information that a is an array and with this, how much elements it had. The 3 is completely ignored by the compiler!

If you want to preserve the datatype (including the array element count), you can use a pointer or a reference to an C-Array:

void f(int (&a)[3]); // reference to C-Array with 3 elements
void f(int (*a)[3]); // pointer to C-Array with 3 elements
void f(int a[3]);    // pointer to int
void f(int* a);      // pointer to int

If you want to call functions with Arrays call-by-value, you can use C++-Arrays (std::array) from the C++ standard library:

f(std::array<int, 3> a);

std::array<int, 3> arr = {1, 2, 3};
f(arr); // deep copy

Upvotes: 0

wiRe
wiRe

Reputation: 101

If you can not use C++17, which allows to use std::size(container), you can easily implement your own generic sizeofArray template function as a one-liner:

#include <cstddef>
#include <cstdio>

template< typename T, std::size_t N >
inline constexpr std::size_t sizeofArray( const T(&)[N] ) noexcept { return N; }

int x[10];
void* y[100]; 
long z[1000];
struct {int x; char y; long z;} s[123];

static_assert( sizeofArray(x) == 10, "error" );
static_assert( sizeofArray(y) == 100, "error" );
static_assert( sizeofArray(z) == 1000, "error" );
static_assert( sizeofArray(s) == 123, "error" );

int main() {
    puts( "ok" );
}

test it here: http://cpp.sh/8tio3

Upvotes: 0

KeyC0de
KeyC0de

Reputation: 5257

Since C++17 you can also use the standardized free function: std::size(container) which will return the amount of elements in that container.

example:

std::vector<int> vec = { 1, 2, 3, 4, 8 };
std::cout << std::size(vec) << "\n\n";    // 5

int A[] = {40,10,20};
std::cout << std::size(A) << '\n';      // 3

Upvotes: 14

Matthew McCord
Matthew McCord

Reputation: 469

It seems that if you know the type of elements in the array you can also use that to your advantage with sizeof.

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

cout << sizeof(numList) / sizeof(int);

// => 5

Upvotes: 1

jamesc1101
jamesc1101

Reputation: 185

Use the Microsoft "_countof(array)" Macro. This link to the Microsoft Developer Network explains it and offers an example that demonstrates the difference between "sizeof(array)" and the "_countof(array)" macro.

Microsoft and the "_countof(array)" Macro

Upvotes: 1

Mindaugas P.
Mindaugas P.

Reputation: 21

_countof(my_array) in MSVC

I can thing of only one case: the array contains elements that are of different derived types of the type of the array.

Elements of an array in C++ are objects, not pointers, so you cannot have derived type object as an element.

And like mentioned above, sizeof(my_array) (like _countof() as well) will work just in the scope of array definition.

Upvotes: 2

Wojtek B
Wojtek B

Reputation: 170

I know is old topic but what about simple solution like while loop?

int function count(array[]) {

    int i = 0;

    while(array[i] != NULL) {

        i++;

    }

    return i;

}

I know that is slower than sizeof() but this is another example of array count.

Upvotes: -2

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361532

Let's say I have an array arr. When would the following not give the number of elements of the array: sizeof(arr) / sizeof(arr[0])?

One thing I've often seen new programmers doing this:

void f(Sample *arr)
{
   int count = sizeof(arr)/sizeof(arr[0]); //what would be count? 10?
}

Sample arr[10];
f(arr);

So new programmers think the value of count will be 10. But that's wrong.

Even this is wrong:

void g(Sample arr[]) //even more deceptive form!
{
   int count = sizeof(arr)/sizeof(arr[0]); //count would not be 10  
}

It's all because once you pass an array to any of these functions, it becomes pointer type, and so sizeof(arr) would give the size of pointer, not array!


EDIT:

The following is an elegant way you can pass an array to a function, without letting it to decay into pointer type:

template<size_t N>
void h(Sample (&arr)[N])
{
    size_t count = N; //N is 10, so would be count!
    //you can even do this now:
    //size_t count = sizeof(arr)/sizeof(arr[0]);  it'll return 10!
}
Sample arr[10];
h(arr); //pass : same as before!

Upvotes: 41

par
par

Reputation: 17724

No that would still produce the right value because you must define the array to be either all elements of a single type or pointers to a type. In either case the array size is known at compile time so sizeof(arr) / sizeof(arr[0]) always returns the element count.

Here is an example of how to use this correctly:

int nonDynamicArray[ 4 ];

#define nonDynamicArrayElementCount ( sizeof(nonDynamicArray) / sizeof(nonDynamicArray[ 0 ]) )

I'll go one further here to show when to use this properly. You won't use it very often. It is primarily useful when you want to define an array specifically so you can add elements to it without changing a lot of code later. It is a construct that is primarily useful for maintenance. The canonical example (when I think about it anyway ;-) is building a table of commands for some program that you intend to add more commands to later. In this example to maintain/improve your program all you need to do is add another command to the array and then add the command handler:

char        *commands[] = {  // <--- note intentional lack of explicit array size
    "open",
    "close",
    "abort",
    "crash"
};

#define kCommandsCount  ( sizeof(commands) / sizeof(commands[ 0 ]) )

void processCommand( char *command ) {
    int i;

    for ( i = 0; i < kCommandsCount; ++i ) {
        // if command == commands[ i ] do something (be sure to compare full string)
    }
}

Upvotes: 4

Karl Knechtel
Karl Knechtel

Reputation: 61557

Let's say I have an array arr. When would the following not give the number of elements of the array: sizeof(arr) / sizeof(arr[0])?

In contexts where arr is not actually the array (but instead a pointer to the initial element). Other answers explain how this happens.

I can thing of only one case: the array contains elements that are of different derived types of the type of the array.

This cannot happen (for, fundamentally, the same reason that Java arrays don't play nicely with generics). The array is statically typed; it reserves "slots" of memory that are sized for a specific type (the base type).

Sorry for the trivial question, I am a Java dev and I am rather new to C++.

C++ arrays are not first-class objects. You can use boost::array to make them behave more like Java arrays, but keep in mind that you will still have value semantics rather than reference semantics, just like with everything else. (In particular, this means that you cannot really declare a variable of type analogous to Foo[] in Java, nor replace an array with another one of a different size; the array size is a part of the type.) Use .size() with this class where you would use .length in Java. (It also supplies iterators that provide the usual interface for C++ iterators.)

Upvotes: 1

GManNickG
GManNickG

Reputation: 503983

There are no cases where, given an array arr, that the value of sizeof(arr) / sizeof(arr[0]) is not the count of elements, by the definition of array and sizeof.

In fact, it's even directly mentioned (§5.3.3/2):

.... When applied to an array, the result is the total number of bytes in the array. This implies that the size of an array of n elements is n times the size of an element.

Emphasis mine. Divide by the size of an element, sizeof(arr[0]), to obtain n.

Upvotes: 9

Bj&#246;rn Pollex
Bj&#246;rn Pollex

Reputation: 76838

First off, you can circumvent that problem by using std::vector instead of an array. Second, if you put objects of a derived class into an array of a super class, you will experience slicing, but the good news is, your formula will work. Polymorphic collections in C++ are achieved using pointers. There are three major options here:

Upvotes: 1

EboMike
EboMike

Reputation: 77752

Arrays in C++ are very different from those in Java in that they are completely unmanaged. The compiler or run-time have no idea whatsoever what size the array is.

The information is only known at compile-time if the size is defined in the declaration:

char array[256];

In this case, sizeof(array) gives you the proper size.

If you use a pointer as an array however, the "array" will just be a pointer, and sizeof will not give you any information about the actual size of the array.

STL offers a lot of templates that allow you to have arrays, some of them with size information, some of them with variable sizes, and most of them with good accessors and bounds checking.

Upvotes: 9

Related Questions