How to Reliably Get Size of C-Style Array

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?

Is there *any* way to get the length of a C-style array in C++/G++?

To answer this:

Any hope for non-compiler-specific code?

No.

More generally, if you find yourself needing to do this, then you probably need to reconsider your design. Use a std::vector, for instance.

How can i get size of an array in the called function?

Is there exist an other techniques for having the size information of the passed array in the called function or I'm hitting right on the money?

Yes you can. Put a sentinel value as a last element of array. Then use a loop on a passed array to get the size in that function.

How does C++ find the size of an array?

The sizeof operator returns the size in bytes, not elements.

For single dimensional arrays (not passed as a function argument, which would cause decay to a pointer), you can get the element count by dividing the size of the array by the size of the first element, e.g.

sizeof(oneDArray) / sizeof(oneDArray[0])  // Gets 3

For multidimensional arrays, that would tell you the size of the first dimension, not the number of elements total, so you'd need to drill down deeper:

sizeof(twoDArray) / sizeof(twoDArray[0])  // Gets 2 (first dimension of array)
sizeof(twoDArray) / sizeof(twoDArray[0][0]) // Gets 6 (number of elements)

You can of course explicitly name the type of an element to avoid nested indexing (sizeof(twoDArray) / sizeof(int) get 6 just fine), but I avoid it as a rule; it's too common for an array to change types during development (say, it turns out you need to use int64_t because you have values into the trillions), and if the whole expression isn't in terms of the array, it's easy to overlook it and end up with broken code.

Pointer to an array get size C++

Simple.

Use std::vector<int> Or std::array<int, N> (where N is a compile-time constant).

If you know the size of your array at compile time, and it doens't need to grow at runtime, then use std::array. Else use std::vector.

These are called sequence-container classes which define a member function called size() which returns the number of elements in the container. You can use that whenever you need to know the size. :-)

Read the documentation:

  • std::array with example
  • std::vector with example

When you use std::vector, you should consider using reserve() if you've some vague idea of the number of elements the container is going to hold. That will give you performance benefit.

If you worry about performance of std::vector vs raw-arrays, then read the accepted answer here:

  • Is std::vector so much slower than plain arrays?

It explains why the code in the question is slow, which has nothing to do with std::vector itself, rather its incorrect usage.


If you cannot use either of them, and are forced to use int*, then I would suggest these two alternatives. Choose whatever suits your need.

struct array
{
int *elements; //elements
size_t size; //number of elements
};

That is self-explanatory.

The second one is this: allocate memory for one more element and store the size in the first element as:

int N = howManyElements();
int *array = int new[N+1]; //allocate memory for size storage also!
array[0] = N; //store N in the first element!

//your code : iterate i=1 to i<=N

//must delete it once done
delete []array;

Getting size of dynamic C-style array vs. use of delete[]. Contradiction?

TL;DR The operator delete[] destructs the objects and deallocates the memory. The information N ("number of elements") is required for destructing. The information S ("size of allocated memory") is required for deallocating. S is always stored and can be queried by compiler extensions. N is only stored if destructing objects requires calling destructors. If N is stored, where it is stored is implementation-dependent.


The operator delete [] has to do two things:

a) destructing the objects (calling destructors, if necessary) and

b) deallocating the memory.

Let's first discuss (de)allocation, which
is delegated to the C functions malloc and free by many compilers (like GCC). The function malloc takes the number of bytes to be allocated as a parameter and returns a pointer. The function free takes only a pointer; the number of bytes is not necessary. This means that the memory allocating functions have to keep track how many bytes have been allocated. There could be a function to query how many bytes have been allocated (in Linux this can be done with malloc_usable_size, in Windows with _msize). This is not what you want because this does not tell you the size of an array but the amount of memory allocated. Since malloc is not necessarily giving you exactly as much memory as you have asked for, you cannot compute the array size from the result of malloc_usable_size:

#include <iostream>
#include <malloc.h>

int main()
{
std::cout << malloc_usable_size(malloc(42)) << std::endl;
}

This example gives you 56, not 42: http://cpp.sh/2wdm4

Note that applying malloc_usable_size (or _msize) to the result of new is undefined behavior.

So, let's now discuss construction and destruction of objects. Here, you have two ways of delete: delete (for single objects) and delete[] (for arrays). In very old versions of C++, you had to pass the size of the array to the delete[]-operator. As you mentioned, nowadays, this is not the case. The compiler tracks this information. GCC adds a small field prior the beginning of the array, where the size of the array is stored such that it knows how often the destructor has to be called. You might query that:

#include <iostream>

struct foo {
char a;
~foo() {}
};

int main()
{
foo * ptr = new foo[42];
std::cout << *(((std::size_t*)ptr)-1) << std::endl;
}

This code gives you 42: http://cpp.sh/7mbqq

Just for the protocol: This is undefined behavior, but with the current version of GCC it works.

So, you might ask yourself why there is no function to query this information. The answer is that GCC doesn't always store this information. There might be cases where destruction of the objects is a no-operation (and the compiler is able to figure that out). Consider the following example:

#include <iostream>

struct foo {
char a;
//~foo() {}
};

int main()
{
foo * ptr = new foo[42];
std::cout << *(((std::size_t*)ptr)-1) << std::endl;
}

Here, the answer is not 42 any more: http://cpp.sh/2rzfb

The answer is just garbage - the code was undefined behavior again.

Why? Because the compiler does not need to call a destructor, so it does not need to store the information. And, yes, in this case the compiler does not add code that keeps track how many objects have been created. Only the number of allocated bytes (which might be 56, see above) is known.

C++ C style array as argument with wrong syntax

This is the right header file class:

class Enemy
{
public:
Enemy(long hp, long dmg);
Enemy(long hp, long dmg, std::vector<MonsterSkill> skills);
~Enemy();
long hp;
long dmg;
std::vector<MonsterSkill> skills;
void getAttacked(PlayerSkill skill, Weapon weapon);
private:
void dying();
};

A vector is right here because I don't know at compile time how many skills each enemy will have.

How can I get the size of an array from a pointer in C?

No, there is no way to get this information without depending strongly on the implementation details of malloc. In particular, malloc may allocate more bytes than you request (e.g. for efficiency in a particular memory architecture). It would be much better to redesign your code so that you keep track of n explicitly. The alternative is at least as much redesign and a much more dangerous approach (given that it's non-standard, abuses the semantics of pointers, and will be a maintenance nightmare for those that come after you): store the lengthn at the malloc'd address, followed by the array. Allocation would then be:

void *p = calloc(sizeof(struct mystruct) * n + sizeof(unsigned long int),1));
*((unsigned long int*)p) = n;

n is now stored at *((unsigned long int*)p) and the start of your array is now

void *arr = p+sizeof(unsigned long int);

Edit: Just to play devil's advocate... I know that these "solutions" all require redesigns, but let's play it out.
Of course, the solution presented above is just a hacky implementation of a (well-packed) struct. You might as well define:

typedef struct { 
unsigned int n;
void *arr;
} arrInfo;

and pass around arrInfos rather than raw pointers.

Now we're cooking. But as long as you're redesigning, why stop here? What you really want is an abstract data type (ADT). Any introductory text for an algorithms and data structures class would do it. An ADT defines the public interface of a data type but hides the implementation of that data type. Thus, publicly an ADT for an array might look like

typedef void* arrayInfo;
(arrayInfo)newArrayInfo(unsignd int n, unsigned int itemSize);
(void)deleteArrayInfo(arrayInfo);
(unsigned int)arrayLength(arrayInfo);
(void*)arrayPtr(arrayInfo);
...

In other words, an ADT is a form of data and behavior encapsulation... in other words, it's about as close as you can get to Object-Oriented Programming using straight C. Unless you're stuck on a platform that doesn't have a C++ compiler, you might as well go whole hog and just use an STL std::vector.

There, we've taken a simple question about C and ended up at C++. God help us all.

How to get the size of the used space in an array? (NOT sizeof); c++

Maybe you want strlen(arr) here. It must be null terminated, otherwise the cout << arr would not have worked.

You would need to #include <cstring>



Related Topics



Leave a reply



Submit