Get the size of the array by reference - c++

I created a vector of pointers to an array
vector<PxVec3*> gConvexMeshVertexesArrays;
I added a link to the array with elements
static PxVec3 convexVerts[] = {
PxVec3(-0.000000, 1.295039, -5.117647),
PxVec3(-9.881939, 10.235294, 5.235294),
PxVec3(-10.117647, 10.235294, 5.235294)
}
Then I try to get the size of this array
cout << "in = " << sizeof(convexVerts) / sizeof(PxVec3) << endl; //ok
gConvexMeshVertexesArrays.push_back(convexVerts);
cout << "in2 = " << sizeof(*(gConvexMeshVertexesArrays.back())) / sizeof(PxVec3) << endl; //wrong!
How can I make the second option work correctly? After all, back() returns a reference to the pointer and the size of the array I can't get from the reference.
Thanks.

There is no way to know the size of some memory a pointer may be pointing to because pointers have no information about what data they are pointing to (except the declared type, that is).
If you want a (pointer, size) pair, take a look at std::span in C++20 and similar types provided in some libraries.
The well-known sizeof(array) / sizeof(element) expression works for arrays (and it does so at compile-time) because arrays statically know their entire size (plus they are contiguous, etc.).

I created a vector of pointers to an array
vector<PxVec3*> gConvexMeshVertexesArrays;
You've created a vector of pointers to PxVec3, which I assume is not an array. Those pointed PxVec3 objects may be elements of an array though.
cout << "in2 = " << sizeof(*(gConvexMeshVertexesArrays.back())) / sizeof(PxVec3) << endl; //wrong!
How can I make the second option work correctly?
This would work, if you actually did have a vector of pointers to an array:
std::vector<PxVec3(*)[3]> gConvexMeshVertexesArrays;
This way, indirecting through the pointer to array, you get an lvalue reference to the array itself, and you can get the size of that array the same way as you'd get it from the array directly as you are attempting here.
If you instead have a pointer to an element of an array, as you do in the example, then there is no general way to get the size of the array that contains the element from that pointer.
In some particular cases, there may be a way to calculate the size however. For example, you could decide that certain value represents the end of the array, in which case you can iterate the successive sibling of the pointed object until you reach the terminator. This is conventionally done with character strings where the null terminator character represents end of a string.
In case you want to store a pointer to an element of an array, and want to know the size and cannot choose a value as terminator, then you would typically store the size along with the pointer.
gConvexMeshVertexesArrays.push_back(convexVerts);
I successfully add a pointer to an array to the vector and then try to get the size of that array.
No, you don't. You push a pointer to the first element of an array into the vector. Then you get the size of the array element (whether you intended that or not), which you divide by the size of the element, which always results in 1.

Related

Can someone explain what this pointer refers to here?

I came across a prime number generator in which they used this line of code
bool *numberlist = new bool[size+1];
What does this create?
The code also has this in a for loop:
numberlist[i*j]=true;
Isnt numberlist a pointer? how can you iterate through it like an array.
To break it down, the first line of code bool *numberlist = new bool[size+1];
declare a dynamic bool arrays that have for size [size+1]. The code in the for loopnumberlist[i*j]=true;means that the element i*j is true. In C++ array decayed to a pointer "more specificaly to a pointer to the first element"(meaning that each time we use an array in a expression, we are actually using a pointer) when we are accessing element of an array using brace operator ([]) we are doing 2 things. One pointer arithemtic(because an array is stored sequentially in memory) and Two dereference the pointer(to access the value that the pointer points to).
The variable numberlist holds a pointer to an array of booleans of size size + 1.
You can access the elements by means of operator []. Pointer arithmetic applies here too as you are iterating through boolean elements in memory. In a for loop you could use:
for (size_t i = 0; i < size; i++) {
std::cout << "numberlist[ " << i << "] = " << numberlist[i] << std::endl;
}
If you are iterating through a 2D matrix, for example, it is normal to store items ordered by rows and use two for-loops to iterate through rows/columns. This might be the case with your numberlist.

What is the fastest way to obtain an index from a pointer of an array element in C++?

Suppose you have a pointer to an int from an array. Is this the best way to find out which item of the array the pointer points to?
int nmbr = pointer - &array[0];
cout<<"Item number "<<nmbr+1;
If the pointer pointed to the 6th item, would this always print "Item number 6"? Is this error-prone? Is there a faster way to do it? Iterating over the array won't work because of possible duplicate values, but does this always work? In this situation we assume the array starts from item 0 to item x. Is there a situation in which an array's items aren't stored in a continuous line (if the array was initialized as int array[x];)?
Assuming pointer is known to point at an element of array, the
std::ptrdiff_t nmbr = pointer - array;
will do it. If pointer does not point at an element of the array, the behaviour is undefined. std::ptrdiff_t is declared in the standard header <cstddef>, and is an implementation-defined signed integral type. Using int is not a good idea, particularly for large arrays, since std::ptrdiff_t may be able to represent a larger range of values than an int (and, if the value is larger than an int can represent, converting the result to int also gives undefined behaviour).
The +1s in your code are incorrect, since array indexing in C++ is zero based.
All arrays, in the sense of something declared as
some_type array[some_positive_value];
have contiguous elements. Note that C++ does not support C's VLAs (variable length arrays) i.e. some_positive_value must be known at compile time.
As mentioned by XTF, yes it is guaranteed to work. There is however, no need for taking the address of the 0'th element, just use array as it is.
For a more generic solution, that will also work on other containers you could consider the following examples:
#include <iostream>
#include <iterator>
#include <array>
int main()
{
{
int array[10];
int * p = &array[5]; // Somehow get a pointer to the sixth element
std::cout << std::distance(std::begin(array), p) << std::endl;
}
{
std::array<int, 10> array;
int * p = &array[5]; // Somehow get a pointer to the sixth element
std::cout << std::distance(std::begin(array), p) << std::endl;
}
}
Both +1's look wrong..
But yes, this is the fastest and simplest way. It's guaranteed to work.

How to retrieve the size of this array?

I'm using IMidiQueue to queue/add IMidiMsg objects to my IMidiQueue mMIDICreated;
At some times, I'd like to retrieve the number of items I've added on it. I've tried this:
char buffer[50];
sprintf(buffer, "size %d\n", sizeof(mMIDICreated) / sizeof(IMidiMsg));
OutputDebugString(buffer);
but after adding 8 items:
for (int i = 0; i < 4; i++) {
IMidiMsg* one = new IMidiMsg;
// ...
mMIDICreated.Add(one);
IMidiMsg* two = new IMidiMsg;
// ...
mMIDICreated.Add(two);
}
it returns 2, not 8. Where am I wrong?
sizeof will return the size of the object or type itself, it's a constant and is evaluated at compile-time, has nothing to do with the number of items which could be known only at run-time.
You should use IMidiQueue::ToDo:
Returns the number of MIDI messages in the queue.
Assuming that mMIDICreated is a pointer, doing sizeof on a pointer returns the size of the actual pointer and not what it points to. Also note that when passing an array to a function, it decays to a pointer to its first element.
If a function needs the number of elements in an array, you need to pass that along to the function as an argument.
An alternate solution, and one that I recommend over using plain arrays/pointers, is to use std::array (for arrays that are known at time of compilation) and std::vector for "run-time" or dynamic arrays.
Looking at your link:
class IMidiQueue
{
...
IMidiMsg* mBuf;
}
The buffer that stores the elements is not taken into the size returned by sizeof(). Only the size of the pointer itself.
However, there is also a method int GetSize() that could be useful to you.

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).

Dynamic array allocation in C++ question

I have a struct of type Duplicate
I have a variable of type int called stringSize, it has a value of 5
I am creating a dynamic array:
Duplicate *duplicates;
duplicates = new Duplicate[stringSize - 1];
Later I delete[] duplicates;
I'm getting one member in that array only? I've verified that stringSize - 1 = 4 with a debug walk through. What can I do to get the 4 members I need?
Any help appreciated,
Thanks // :)
Duplicate *duplicates;
duplicates = new Duplicate[stringSize - 1];
Indeed gives you duplicates[0-3] (Assuming stringSize - 1 is 4, like you say). How are you determining you're getting less?
I suspect you may be doing something like: sizeof(duplicates) / sizeof(duplicates[0]), and on an off-change getting one. The above code only works for statically allocated arrays, where sizeof(duplicates) would match the size of the array, in bytes. In your case, it'll simply return the size of a pointer on your system. (duplicates is a Duplicate*)
And mandatory: Use std::vector if this is "real" code.
Your debugger is doing the best it can. As far is it's concerned, you've merely got a pointer to some data. Consider:
Duplicate foo;
Duplicate *duplicates_A;
duplicates_A = &foo; // points to one Duplicate
Duplicate *duplicates_B;
duplicates_B = new Duplicate[4]; // points to memory containing 4 Duplicate's
bar(duplicates_A);
bar(duplicates_B);
void bar(Duplicate* p)
{
// is p a pointer to one value, or is it an array?
// we can't tell, and this is the same boat your debugger is in
}
How should the debugger, just given a pointer, know if it's pointing to an array or just one value? It cannot, safely. (It would have to determine, somehow, if the pointer was to an array, and the size of that array.)
You can't use sizeof to determine the size of a dynamic array. In fact, there isn't a standard API to determine the size of a dynamic array.
Use std::vector if you need to access the size.
If you use a debugger to view the elements you get, the problem may be that the type of your variable is Duplicate* which is just a pointer (which in C happens to also be an array but the type is just a pointer to one instance of Duplicate.