Calculate length of double pointer array - c++

I have a double pointer Array of a structure:
typedef struct Position{
int x;
int y;
} Position;
Position** array = (Position**)malloc(sizeof(Position*)*10); //10 elements
array[0] = (Position*)malloc(sizeof(Position*));
array[0]->x = 10;
array[0]->y = 5;
Can I calculate the length of set array and if so, how?
The normal way for arrays does not work :
int length = sizeof(<array>)/sizeof(<array>[0]);

Once you have dynamically allocated an array, there is no way of finding out the number of elements in it.
I once heard of some hacky way to obtain the size of a memory block, (msize) which would allegedly allow you to infer the size of the data within the block, but I would advice against any such weird tricks, because they are not covered by the standard, they represent compiler-vendor-specific extensions.
So, the only way to know the size of your array is to keep the size of the array around. Declare a struct, put the array and its length in the struct, and use that instead of the naked array.

As you marked the question as C++, I would suggest that you use std::vector, then, after you "allocated some memory" (or requested some memory to allocated by std::vector constructor or by using push_back, or resize), you can simply get the size back using by using std::vector::size.
typedef struct Position{
int x;
int y;
} Position;
std::vector<Position> array(10);
array[0].x = 10;
array[0].y = 5;
size_t size = array.size(); // will be 10

Having only a pointer to some memory block, you cannot defer the size of this memory block. So you cannot defer the number of elements in it.
For arrays of pointers, however, you could infer the number of elements in it under the following conditions:
make sure that every pointer (except the last one) points to a valid object.
for the last pointer in the array, make sure that it is always NULL.
Then you can derive the length by counting until you reach NULL.
Maybe there are some other similar strategies.
Solely from the pointer itself, however, you cannot derive the number of elements in it.

Old question, but in case someone needs it:
#include <stdio.h>
...
int main()
{
char **double_pointer_char;
...
int length_counter = 0;
while(double_pointer_char[length_counter])
length_counter++;
...
return 0;
}

Related

How to count the number of elements in an predefined array

I want to count the actual number of elements in the array.
but if I use sizeof() statement it gives me the size of array. not the number of elements present.
int main()
{
int a[10],n;
a[0]=1;
a[1]=5;
a[2]=6;
n=sizeof(a)/sizeof(a[0]);
cout<<"The size of array " <<n;
}
Here it gives me the n value as 10 not 3. Please suggest me a way to derive the number of elements without affecting the performance.
int a[10]; // This would allocate 10 int spaces in the memory;
a[0] = 1; // You are changing whats inside the first allocated space, but you are not changing the number of items in your C array.
Solution 1 (Easy) :
#include <vector>
vector<int> a;
a.push_back(1);
a.push_back(2);
size_t size = a.size(); // to get the size of your vector. would return 2. size_t is the actual type returned by size() method and is an unsigned int.
Solution 2 (Complicated) :
You could create an int variable that you could call e.g. numberOfElements and update it each time you add an element.
This solution is actually used in the implementation of the vector class.
As it have been already mentioned, you should use std::vector or std:array to achieve this behaviour. Declaring simple array means you allocate enough memory on the heap. There is not a way to determine whether this memory is "occupied" with something valid or not, since there is always something (after allocation there are random values on each index of the array).

Passing array values from a function back into a struct

I am currently working on a program that requires a function to figure out array values and then stores those values in arr1[], which has an unknown size and is calculated within the function. It then passes back the entire array along with the size of the array back to the main function. Using a struct, I returned the size, but I cannot return the array for some reason. Can someone please direct me in the right direction with what I'm doing wrong?
Here is my struct:
struct Arr
{
int size_1;
int arr_1[];
};
And here is part of my function that returns the array, where arr1[] is the array in which I need to return:
Arr smallElement(int arr[], int size)
{
Arr tempArr;
for (int count = 0; count < newSize; count++)
{
tempArr.arr_1[count] = arr1[count];
}
return tempArr;
}
This is what I use in my main function to call the function to print the array, but it just prints 3 random numbers every time:
Arr a;
a = smallElement(array, n);
cout << "The array is: ";
for (int count = 0; count < a.size_1; count++)
{
cout << a.arr_1[count] << " ";
}
Inside a struct, int arr_1[] does not define an actual array. It is actually just a placeholder called a flexible array member. In C, this is used by allocating memory for the fully defined part of the struct plus additional space for the array—you have to manually add space when using malloc or other memory allocation. In standard C++, you should not use this. (It is not part of standard C++. It is an extension adopted by some compilers from C, where it is standard.)
When you declared tempArr, it created just the fully defined portion of the struct. When you assigned values to tempArr.arr_1[count], there was no allocated array there, so the behavior is undefined. When you return tempArr, a copy of the struct is returned, but, again, only a copy of the defined portion.
If the caller knows the size the array will be, you may want to have them pass the array to the function, perhaps by allocating it with new or by using std::vector and passing the vector by reference. If the size is not known by the caller, then you may want to have the function allocate the array and return a pointer to it (in which case the caller is responsible for deleting it later), or you may want to pass an empty (or otherwise available for re-use) std::vector to the function, preferably by reference. Inside the function, it can add more elements to the vector, and the std::vector will manage memory allocation for you.

Declaring array of objects on heap with variable array size

I've got a class and I'm going to declare the size of the array (two dimensional) based on input from a user.
so :
class myClass {/*...*/}
int main(){
myClass* arrayObj = new myClass[100][100];
That works fine, and it should put the array on the heap.
But I need to do :
int arraySize;
cin >> arraySize;
myClass* arrayObj = new myClass[arraySize][arraySize];
I am getting the error :
"arraySize" cannot appear in a constant-expression.
I'm assuming that means that I can only have constants in the declaration of the array, but if not, then how can I do it?
The array is too big to fit on the stack, that is why I am doing it on the heap in the first place.
Edit : I've got it working with the pointers, but I'm having another problem, I have a function that is using the array, ie.
void myFunction()
{
/*...*/
arrayObj[something][something].variable = somethingElse // error here
}
int main ()
{
/*...*/
int arraySize;
cin >> arraySize;
MyClass **arrayObj = new MyClass*[arraySize]
for (int i = 0; i < arraySize; i++) arrayObj[i] = new MyClass[arraySize]
/*...*/
}
I'm getting : error: 'arrayObj' was not declared in this scope.
I can see why, but it's on the heap and it's a pointer, shouldn't it be global? If not, how would I make it global?
First of all you are mistaken saying that this
class myClass {/*...*/}
int main(){
myClass* arrayObj = new myClass[100][100];
works fine. The compiler shall issue an error because there is no implicit conversion from myClass ( * )[100] to myClass *
As for your problem then you should use the following approach:
myClass **arrayObj = new myClass *[arraySize];
for ( int = 0; i < arraySize; i++ ) arrayObj[i] = new myClass[arraySize];
C++ doesn't really have a built-in model of variable sized multi-dimensional arrays. Only the outermost dimension can vary at run-time, all other dimensions are fixed. The background is how C++ does address arithmetic: when adding an offset to a pointer it is advanced by the size of an object with a statically determined size.
If you want to have a multi-dimensional array varying in other dimensions, you'll need to use a suitable class or implement one yourself (the standard C++ library has std::valarray<T> to sort of deal with multi-dimensional arrays but their use is, let say, not entirely straight forward). The easiest approach is probably to use a std::vector<std::vector<myClass> >.
A more efficient approach is to allocate a large std::vector<myClass> as a member of a class and have operator[]() for this class return a view to a corresponding section of this array. For starters I would probably just use a std::vector<std::vector<myClass> > wrapped into a class and change the implementation if it turns out to be too inefficient.
If you must use arrays, then another way to get around this is impose a limit on the number of elements in the array and make sure that this limit is enforced in your code. This is one of the disadvantages of using arrays vs. std::vectors. Arrays are a fixed size while vectors can keep growing dynamically. By the way, what do you mean by "The array is too big to fit on the stack, that is why I am doing it on the heap in the first place."? If it is too big to fit on the stack, then maybe we should look at why the array is so large in the first place. Maybe there is a better way to solve whatever problem you're trying to deal with.

how do I empty/clear vector and array in c++

let's say I have a class, A
Class A {
int x[100];
vector<int> y;
Fill(x);
Fill(y.begin());
B(x);
B(y.begin());
}
Class Fill (pointer) {
*pointer = 0;
++pointer;
*pointer = 1;
++pointer
}
Class B(container) {
//how do I clear/empty the array and the vector passed by class A given only the pointers to them?
//I must clear an array and a vector in THIS class.
//I DO NOT want to fill them with 0s.
//x and y.begin are POINTERS to the first element of the container, not containers
}
dsfsdakfgnsdfgsf
dg
sdf
gsdf
ghsdf
g
sdfg
ersg
s
Thank you in advance.
For vector:
some_a_pointer->y.resize(0);
You can't do it with just an iterator (y.begin()).
An array's size can never change, so the best you can do is fill it with 0.
std::vector has a method called clear that will clear all the elements.
So my_vector.clear(); will clear everything. However you can't really do the same for arrays. It's just not possible. At best you can fill them with zeroes or go the wrong way and dynamically allocate the array and then delete it. I would rather not deal with memory issues though so I'd just fill them with zero.
C++11 has a class called std::array<T,N> for static arrays of a compile time size and it has a method called fill that would make filling everything to zero easy (a la looping). You can call it with my_array.fill(0);.

Is it necessary to delete elements as an array shrinks?

I'm a student writing a method that removes zeros from the end of an array of ints, in C++. The array is in a struct, and the struct also has an int that keeps track of the length of the array.
The method examines each element starting from the last, until it encounters the first non-zero element, and marks that one as the "last element" by changing the value of length. Then the method walks back up to the original "last element", deleting those elements that are not out of bounds (the zeros).
The part that deletes the ith element in the array if i is greater than the updated length of the array, looks like this:
if (i > p->length - 1) {
delete (p->elems + i); // free ith elem
That line is wrong, though. Delete takes a pointer, yes? So my feeling is that I need to recover the pointer to the array, and then add i to it so that I will have the memory location of the integer I want to delete.
Is my intuition wrong? Is the error subtle? Or, have I got the entirely wrong idea? I've begun to wonder: do I really need to free these primitives? If they were not primitives I would need to, and in that case, how would I?
have I got the entirely wrong idea?
I'm afraid so.
If you make one new[] call to allocate an array, then you must make one delete[] call to free it:
int *p = new int[10];
...
delete[] p;
If your array is in a struct, and you make one call to allocate the struct, then you must make one call to free it:
struct Foo {
int data[10];
};
Foo *foo = new Foo;
...
delete foo;
There is no way to free part of an array.
An int[10] array actually is 10 integers, in a row (that is, 40 bytes of memory on a 32 bit system, perhaps plus overhead). The integer values which are stored in the array occupy that memory - they are not themselves memory allocations, and they do not need to be freed.
All that said, if you want a variable length array:
that's what std::vector is for
#include <vector>
#include <iostream>
struct Foo {
std::vector<int> vec;
};
int main() {
Foo foo;
// no need for a separate length: the current length of the vector is
std::cout << foo.vec.size() << "\n";
// change the size of the vector to 10 (fills with 0)
foo.vec.resize(10);
// change the size of the vector to 7, discarding the last 3 elements
foo.vec.resize(7);
}
If p->elems is a pointer, then so is p->elems + i (assuming the operation is defined, i.e. i is of integral type) - and p->elems + i == &p->elems[i]
Anyhow, you most likely don't want to (and cannot) delete ints from an array of int (be it dynamically or automatically allocated). That is
int* ptr = new int[10];
delete &ptr[5]; // WRONG!
That is simply something you cannot do. However, if the struct contains the length of the array, you could consider the array "resized" after you change the length information contained by the struct - after all, there is no way to tell the size of the array a pointer points to.
If, however your array is an array of pointers to integers (int*[]) and these pointers point to dynamically allocated memory, then yes, you could delete single items and you'd do it along the lines of your code (you are showing so little code it's difficult to be exact).