Can someone explain what this pointer refers to here? - c++

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.

Related

Get the size of the array by reference

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.

C++ Dereferencing Null ptr error?

I looked before posting, but pardon me if my answer is elsewhere. As part of my homework, I need to create an array of pointers to objects (of different types, but they share a base class). Once the pointers are in the array I need to be able to call member functions on the objects to which they point. I'm able to do this for the first object, but after my program goes through the loop once, I get the following exception: "0xC0000005: Access violation executing location 0x00000000"
Below is my code. Thanks
int main()
{
Sales * publications[5]; //declare an array of pointers
for (int i = 0; i < 5; i++) {
if (i < 3)
publications[i] = new Book();
else
publications[i] = new Tape();
std::cout << std::endl << publications[i] << std::endl;
(*publications)[i].readData();
(*publications)[i].displayData();
}
for (int i = 0; i < 5; i++) { //delete the array to avoid memory leak
delete publications[i];
}
std::cout << std::endl;
system("pause");
return 0;
}
I have already tested the readData and displayData functions and they work just fine.
This:
(*publications)[i].readData();
Should be:
publications[i]->readData();
publications is an array of pointers.
(*publications)[i].readData();
In this code snippet, the order of operations is out of order. The * dereference operator is going to take precedence over the [] array syntax operator due to the parenthesis.
The first thing that is going to happen is publications (the array) is going to be dereferenced - not the element located at index i. This will always give you the first element in the array, as an array variable is just the address of the first element.
The second operation that takes place is that a byte offset (sizeof(Sales) * i)) is added to the memory address returned by the dereference. When the index i is 0, this is not a problem since there is no offset to add and an object exists at the calculated memory location. However, once you have an index not equal to 0, the calculated memory address does not point at a valid Sales object, so you may or may not crash, depending on what actually lies at the memory location.
The correct order of operations using the given operators is this:
(*(publications[i])).readData();
Using the -> operator is preferred instead:
publications[i]->readData();
Now, the [] array-syntax operator takes precedence, offsetting the address of the array to an element within the array, and then either *. or -> is used to dereference that element's pointer to reach the object, as expected.

Replace vector of vector with flat memory structure

I have the following type:
std::vector<std::vector<int>> indicies
where the size of the inner vector is always 2. The problem is, that vectors are non-contiguous in memory. I would like to replace the inner vector with something contiguous so that I can cast the flattened array:
int *array_a = (int *) &(a[0][0])
It would be nice if the new type has the [] operator, so that I don't have to change the whole code. (I could also implement it myself if necessary). My ideas are either:
std::vector<std::array<int, 2>>
or
std::vector<std::pair<int, int>>
How do these look in memory? I wrote a small test:
#include <iostream>
#include <array>
#include <vector>
int main(int argc, char *argv[])
{
using namespace std;
vector<array<int, 2>> a(100);
cout << sizeof(array<int, 2>) << endl;
for(auto i = 0; i < 10; i++){
for(auto j = 0; j < 2; j++){
cout << "a[" << i << "][" << j << "] "
<<&(a[i][j]) << endl;
}
}
return 0;
}
which results in:
8
a[0][0] 0x1b72c20
a[0][1] 0x1b72c24
a[1][0] 0x1b72c28
a[1][1] 0x1b72c2c
a[2][0] 0x1b72c30
a[2][1] 0x1b72c34
a[3][0] 0x1b72c38
a[3][1] 0x1b72c3c
a[4][0] 0x1b72c40
a[4][1] 0x1b72c44
a[5][0] 0x1b72c48
a[5][1] 0x1b72c4c
a[6][0] 0x1b72c50
a[6][1] 0x1b72c54
a[7][0] 0x1b72c58
a[7][1] 0x1b72c5c
a[8][0] 0x1b72c60
a[8][1] 0x1b72c64
a[9][0] 0x1b72c68
a[9][1] 0x1b72c6c
It seems to work in this case. Is this behavior in the standard or just a lucky coincidence? Is there a better way to do this?
An array<int,2> is going to be a struct containing an array int[2]; the standard does not directly mandate it, but there really is no other sane and practical way to do it.
See 23.3.7 [array] within the standard. There is nothing in the standard I can find that requires sizeof(std::array<char, 10>)==1024 to be false. It would be a ridiculous QOI (quality of implementation); every implementation I have seen has sizeof(std::array<T,N>) == N*sizeof(T), and anything else I would consider hostile.
Arrays must be contiguous containers which are aggregates that can be initialized by up to N arguments of types convertible to T.
The standard permits padding after such an array. I am aware of 0 compilers who insert such padding.
A buffer of contiguous std::array<int,2> is not guaranteed to be safely accessed as a flat buffer of int. In fact, aliasing rules almost certainly ban such access as undefined behaviour. You cannot even do this with a int[3][7]! See this SO question and answer, and here, and here.
Most compilers will make what you describe work, but the optimizer might decide that access through an int* and through the array<int,2>* cannot access the same memory, and generate insane results. It does not seem worth it.
A standards compliant approach would be to write an array view type (that takes two pointers and forms an iterable range with [] overloaded). Then write a 2d view of a flat buffer, with the lower dimension either a runtime or compile time value. Its [] would then return an array view.
There is going to be code in boost and other "standard extension" libraries to do this for you.
Merge the 2d view with a type owning a vector, and you get your 2d vector.
The only behaviour difference is that when the old vector of vector code copies the lower dimension (like auto inner=outer[i]) it copies data, afer it will instead create a view.
Is there a better way to do this?
I recently finished yet-another-version of Game-of-Life.
The game board is 2d, and yes, the vector of vectors has wasted space in it.
In my recent effort I chose to try a 1d vector for the 2d game board.
typedef std::vector<Cell_t*> GameBoard_t;
Then I created a simple indexing function, for when use of row/col added to the code's readability:
inline size_t gbIndx(int row, int col)
{ return ((row * MAXCOL) + col); }
Example: accessing row 27, col 33:
Cell_t* cell = gameBoard[ gbIndx(27, 33) ];
All the Cell_t* in gameBoard are now packed back to back (definition of vector) and trivial to access (initialize, display, etc) in row/col order using gbIndx().
In addition, I could use the simple index for various efforts:
void setAliveRandom(const GameBoard_t& gameBoard)
{
GameBoard_t myVec(m_gameBoard); // copy cell vector
time_t seed = std::chrono::system_clock::
now().time_since_epoch().count();
// randomize copy's element order
std::shuffle (myVec.begin(), myVec.end(), std::default_random_engine(seed));
int count = 0;
for ( auto it : myVec )
{
if (count & 1) it->setAlive(); // touch odd elements
count += 1;
}
}
I was surprised by how often I did not need row/col indexing.
As far as I know, std::vector are contiguous in memory. Take a look at this questions:
Why is std::vector contiguous?,
Are std::vector elements guaranteed to be contiguous?
In case you have to resize an inner vector, you wouldn't have the whole structure contiguous, but the inner vectors would still be it. If you use a vector of vectors, though, you'd have a fully contiguous structure (and I edit here, sorry I misunderstood your question) meaning that the pointers that point to your inner vectors will also be contiguous.
If you want to implement a structure that is always contiguous, from the first element of the first vector to the last element of the last vector, you can implement it as a custom class that has a vector<int> and elems_per_vector that indicates the number of elements in each inner vector.
Then, you can overload the operator(), so to access to a(i,j) you are actually accessing a.vector[a.elems_per_vector*i+j]. To insert new elements, though, and in order to keep the inner vectors at constant size between them, you'll have to make as many inserts as inner vectors you have.

C++ getting the size of an array

I'm new to programming and I was wondering, how to get the size of an array, that is, get the size of how many elements are inside the array. For example if I declare an array of size 10, but only input 3 elements into the array, how would I determine the size of this array? If I don't know how many elements I placed in initially.
If you declare an array, e.g. int array[10], then its size is always 10 * sizeof(int). There is no way to know how many times you've accessed it; you'd need to keep track of that manually.
You should consider using container classes, e.g. std::vector:
std::vector<int> vec;
vec.push_back(5);
vec.push_back(10);
vec.push_back(42);
std::cout << vec.size() << "\n"; // Prints "3"
If you declare an old-style array of 10 elements, e.g. std::string words[10], the size of the array is always 10 strings. Even with the new style (std::array), it would be a fixed size.
You might be looking for a std::vector<>. This doesn't have a fixed size, but does have a .size() method. Therefore, if you add three elements to it, it will have .size()==3
to get the array size (in number of elements) assuming you do not know it in advance
use sizeof(a)/sizeof(a[0])
see the below example program. I used C but it should carry over to C++ just fine
#include <stdio.h>
int main(){
int a[10];
printf("%d elements\n",sizeof(a)/sizeof(a[0]));
return 0;
}
//output: 10 elements
There's several possible ways, but they depend on your definition.
If you know there is a value the user won't input (also known as a sentinel value), you can use a function like memset, to set the entire array to that unused value. You would then iterate through the list counting all the variables in the list that don't match that value.
The other way is to build your own array class, which counts whenever the array is modified (you'd have to overload the = and [] functions as appropriate).
You could also build a dynamically linked list, so as the user adds variables, the count can either be determined by walking the list or keeping count.
But, if you're taking the array as the basic array, with no idea as to it's actual starting state, and no idea what to expect from the user (given this is your program, this shouldn't occur), then generally speaking, no, there is known way to know this.
You maintain a counter variable count initialized to 0.
Whenever you are adding to array increment the count by 1.
Whenever you are removing from array decrement the count by 1.
anytime count will give you the size of the array.
Suggestion:
int[10] arr;
//init all to null
for (int i =0; i < 10; i++)
arr[i] = 0;
arr[0]=1;
arr[2]=5;
int sz = 0;
for (int j = 0; j < 10; j++)
if (arr[j] != 0) sz++;

Creating arrays on the heap and addressing them with pointers

I'm having trouble understanding the following bit of code that I was hoping would create an array on the heap and fill it with the characters 9 down to 0 (I know I could just index the array like a normal stack array with [] notation to do this but I'm doing it this way to try to understand pointers in more depth):
int *ptrHeapArray = new int[10];
for(int f=9; f>=0 ;f--)
{
*ptrHeapArray = f;
ptrHeapArray++;
}
for(int f=0; f<10; f++)
cout << ptrHeapArray[f] << "\n";
It prints out compleletly unexpected values.
As I understand the above, the 'new' command creates an array on the heap and sends me back a pointer to the address where the array is. Since the pointer I assign (ptrHeapArray) is of int size I assumed I could use pointer post incrementing to navigate through the array. However the results indicate that my assumptions are wrong.
This got me to thinking that perhaps the pointer passed back by the 'new' keyword is just a pointer to the whole array and can't be used to step through the array for some reason.
So I tried creating another pointer to the pointer returned by the 'new' keyword and used that to do my array population:
int *ptrHeapArray = new int[10]; //array to hold FRANK data in 32 bit chunks
int *ptrToHeapArrayPointer = ptrHeapArray;
for(int f=9; f>=0 ;f--)
{
*ptrToHeapArrayPointer = f;
ptrToHeapArrayPointer++;
}
for(int f=0; f<10; f++)
cout << ptrHeapArray[f] << "\n";
This worked fine.
Can anyone explain to me why I had to do this and couldn't just have used the pointer passed backed to me by the 'new' keyword?
Thanks
The line
ptrHeapArray++;
in your first for loop increments the pointer, such that it doesn't point to the beginning of the array anymore.
The line
int *ptrHeapArray = new int[10];
allocates the memory for 10 integers and points ptrHeapArray to the beginning of that memory. In your for loop you then move this pointer. When ptrHeapArray points to the third of the integers:
[0] [1] [2] [3] [4]
^ ^ ^
orig. | |
| +-- ptrHeapArray[2]
|
+-- ptrHeapArray now points here
then ptrHeapArray[2] would give you the integer at the position orignally numbered with 4.
You are modifying the pointer in code. After the first loop in the first snippet, the pointer will point to the end of the array rather than the beginning. To make things clearer, this would work too (not suggested but demonstrates the behavior):
int *ptrHeapArray = new int[10];
for(int f=9; f>=0 ;f--)
{
*ptrHeapArray = f;
ptrHeapArray++;
}
ptrHeapArray -= 10; // reset the pointer to its original location
for(int f=0; f<10; f++)
cout << ptrHeapArray[f] << "\n";
Your ptrToHeapArrayPointer is misnamed, it is just a standard int ptr that you've pointed to the same place as ptrHeapArray. If you renamed it to currentPositionPtr your code might make more sense to you.
When you do ptrHeapArray++ it inscrements ptrHeapArray. When you come to print out the data ptrHeapArray no longer points to the start of the array.
The problem is that in your first example ptrHeapArray is initially set to the beginning of the array. As you iterate through your loop you are incrementing the pointer, and by the end of the for loop you are pointing to the last element in the array. When you go through the for loop to display all of your values, you are indexing to values past the end of the array since ptrHeapArray is pointing to the last element in the array you allocated.
It is also important to remember, that you should probably make sure not to loose the original pointer you got back from using the new operator so that you can properly free up the memory that was allocated on the heap.
In the first loop you incremented your pointer ptrHeapArray until the end of array. So after executing the first for loop your pointer is pointing to end of the array and not at the beggining. Hence, when you are trying to print the contents of the array, you are accessing invalid memory allocations and the behavior will be unexpected. In the second case, you are taking a copy of your starting address before assigning values to the array. So when you try to print the contents using the copy, it will be pointing to the beginning of the array.