c++: understanding dynamic arrays - c++

I am trying to understang a dynamic array. In this case - an array of pointers.
This program is Ok to me - it is working, everything is fine.
What troubles me is how the array is organized in the heap.
Let us launch it, that will be our example:
pn 00456878
pn[0] 003AFB90
pn[1] 003AFB80
pn[2] 003AFB70
Will you be so kind as to help me understand three matters:
1) Why the address of pn[0] is higher than that of pn[2]? I seemed to have assigned pn[0] before pn[1] and pn[2]?
2) I allocated memory in the heap for 3 elements of sizeof(POINT).
sizeof(POINT) = 8.
003AFB70 + 8 = 3AFB78. Why the next element is 003AFB80?
3) I have formed an opinion that an array in the heap looks as follows:
pn->pn[0]
pn[1]
pn[2]
pn is a base address. The address of pn[0] = base address + 0.
Judging from what I can see here we can conclude that there is a gap between a base address and the first element. Is it for some auxiliarry data or what is it for?
Thank you in advance.
My code is:
#include "stdafx.h"
#include <iostream>
using namespace std;
struct POINT
{
int x;
int y;
};
POINT ** pn;
POINT ** tmp;
int _tmain(int argc, _TCHAR* argv[])
{
int counter = 3;
POINT p_tmp;
cout << "sizeof(POINT): " << sizeof(POINT) << endl;
pn = new POINT * [counter];
POINT a = {0, 0};
POINT b = {1, 1};
POINT c = {2, 2};
pn[0] = &a;
pn[1] = &b;
pn[2] = &c;
cout << "pn "<< pn << endl;
cout << "pn[0] "<< pn[0] << endl;
cout << "pn[1] "<< pn[1] << endl;
cout << "pn[2] "<< pn[2] << endl;
cin.get();
POINT m = * pn[0];
POINT n = * pn[1];
POINT k = * pn[2];
cout << m.x << ","<<m.y<< endl;
cout << n.x << ","<<n.y<< endl;
cout << k.x << ","<<k.y<< endl;
cin.get();
tmp = new POINT * [counter];
memcpy(tmp, pn, (counter * sizeof(POINT)));
for (int i = 0; i < counter; i++)
{
cout << "tmp[" << i << "] "<< tmp[i] << endl;
}
cin.get();
delete[] pn;
pn = tmp;
m = * pn[0];
n = * pn[1];
k = * pn[2];
cout << m.x << ","<<m.y<< endl;
cout << n.x << ","<<n.y<< endl;
cout << k.x << ","<<k.y<< endl;
cin.get();
return 0;
}

Your confusion arises from the fact that your array contains POINT*s and not POINTs.
Why the address of pn[0] is higher than that of pn[2]? I seemed to have assigned pn[0] before pn[1] and pn[2]?
It's not the address of pn[0] that you are printing, it's its value. The address of pn[0] is denoted by &pn[0].
POINT a = {0, 0};
POINT b = {1, 1};
POINT c = {2, 2};
pn[0] = &a;
pn[1] = &b;
pn[2] = &c;
Here you put in pn the addresses of a, b and c, which are POINTS you declared on the stack. The stack grows from upper addresses to lower addresses, therefore &a > &b > &c.
I allocated memory in the heap for 3 elements of sizeof(POINT). sizeof(POINT) = 8. 003AFB70 + 8 = 3AFB78. Why the next element is 003AFB80?
No, you allocated memory in the heap for 3 elements of sizeof(POINT*) (pointer to POINT, which happen to also be 8 bytes). You allocated an array of three pointers on the heap, but the pointees are on the stack.
In the end, your array looks like this:
(some address) pn-> (00456878) pn[0]-> (003AFB90) a
(00456880) pn[1]-> (003AFB80) b
(00456888) pn[2]-> (003AFB70) c
The pointer pn is static memory, but points to 3 pointers on the heap that point back to 3 elements on the stack.
If you wanted to have everything on the heap, you'd do it like this:
Point **pn = new POINT*[counter];
for (int i = 0; i < counter; ++i)
pn[i] = new POINT;
In this layout, the pointer pn is in static memory, but points to 3 pointers on the heap that point to 3 elements on the heap.

Related

copying static array to dynamic array c++

So I was playing around with some basics in c++ when I noticed this:
int * ptr = new int[3], arr[3] = { 11,13,15 };
for (int i = 0; i < 3; i++)
ptr[i] = arr[i];
cout << ptr[0] << ' ' << ptr[1] << ' ' << ptr[2] << endl;
this code will perfectly insert and print out the values: 11 13 15.
Whereas when I write it this way:
int size=0, * ptr = new int[size], arr[3] = { 11,13,15 };
for (int i = 0; i < 3; i++)
{
ptr = new int[++size];
ptr[i] = arr[i];
}
cout << ptr[0] << ' ' << ptr[1] << ' ' << ptr[2] << endl;
When I increment the size one value at a time, it prints out:
-842150451 -842150451 15
Why is it that when I define the total size at the beginning, the values are properly inserted, however when I increment one step at a time it does not? Also, is there any way to write the second code but in a way where it works please?
As #Ch3esteR points out in the comment. The problem is that you are reallocating your
array on each iteration, and thereby zeroing (or in your case, catching some random
values on the heap).
I would say that the bigger solution might be to use standard containers for handling memory. Here is a solution for fixing your original code original() and a proposed alternative for how to handle dynamic arrays with std::vector.
#include <vector>
#include <iostream>
using namespace std;
void original() {
const int arr[3] = { 11,13,15 };
const int size=3;
auto ptr = new int[size]; // this is what you want to do
std::copy(arr, arr + size, ptr); // Standard function for copying
cout << ptr[0] << ' ' << ptr[1] << ' ' << ptr[2] << endl;
}
int main() {
original();
const int arr[3] = { 11,13,15 }; // You might want to make this a std::vector too
std::vector<int> result{arr, arr + 3};
// std::vector<int> result; // Or if the question was how to do it dynamically
// for (auto i: arr)
// {
// result.push_back(i); // Dynamic add
// }
cout << result[0] << ' ' << result[1] << ' ' << result[2] << endl;
}
On request: How to do it with pointers (don't do this unless you have some external constraint that forces you to do this, like a teacher)
#include <iostream>
using namespace std;
// Reallocate memory and delete the old pointer
int *resize(int *arr, size_t oldSize, size_t newSize) {
auto newArr = new int[newSize];
auto copySize = std::min(oldSize, newSize); // Handle both growing and shrinking resize
std::copy(arr, arr + copySize, newArr); // Copy your old data
// Or do it like this
// for (size_t i = 0; i < copySize, ++i) {
// newArray[i] = arr[i]
// }
delete [] arr;
return newArr;
}
int main() {
auto arr = new int[2] { 11,13 }; // Observe 'new' here
size_t size = 3;
// "resize" the array arr (in practice you are just creating a new one)
arr = resize(arr, size, size + 1);
// Assign your new value
arr[2] = 14;
cout << arr[0] << ' ' << arr[1] << ' ' << arr[2] << endl;
delete [] arr; // Remember, try to not manual memory management,
// only use it in class when you are learning the basics, otherwise use
// std::unique_ptr or std::shared_ptr
}

Why do we have to assign a temporary pointer to an array in a for loop?

I'm pretty new to C++, and I'm trying to understand why we need to assign a pointer to an array assuming the array size is known like the first part of the loop here.
for(int * ptr = arr; ptr < arr + arrSize; ptr++)
Any help would be appreciated.
For starters array designators used in expressions with rare exceptions are converted to pointers to their first elements.
So in this declaration
int * ptr = arr
there is being created local variable ptr that will point to the first element of the array arr.
This expression
arr + arrSize
points to one past the last element of the array arr.
So within the loop due to increments of the pointer ptr all elements of the array are sequentially accessed until the pointer ptr will point to one past the last element of the array.
Here is a demonstrative program.
#include <iostream>
int main()
{
const size_t arrSize = 5;
int arr[arrSize] = { 1, 2, 3, 4, 5 };
size_t i = 0;
for ( int *ptr = arr; ptr != arr + arrSize; ptr++ )
{
std::cout << "ptr = " << ptr << ", &arr[" << i << "] = " << &arr[i] << '\n';
std::cout << "*ptr = " << *ptr << ", arr[" << i << "] = " << arr[i] << '\n';
std::cout << '\n';
i++;
}
return 0;
}
Its output might look like
ptr = 0x7ffeb74dbd00, &arr[0] = 0x7ffeb74dbd00
*ptr = 1, arr[0] = 1
ptr = 0x7ffeb74dbd04, &arr[1] = 0x7ffeb74dbd04
*ptr = 2, arr[1] = 2
ptr = 0x7ffeb74dbd08, &arr[2] = 0x7ffeb74dbd08
*ptr = 3, arr[2] = 3
ptr = 0x7ffeb74dbd0c, &arr[3] = 0x7ffeb74dbd0c
*ptr = 4, arr[3] = 4
ptr = 0x7ffeb74dbd10, &arr[4] = 0x7ffeb74dbd10
*ptr = 5, arr[4] = 5
Pay attention to that in this expression
arr + arrSize
there is used the so-called pointer arithmetic. For example
( arr + arrSize ) - arr
gives the number of elements arrSize between the two pointer expressions arr + arrSize and arr.

How do I reiterate through a pointer array?

My program is supposed to iterate through an array for as many times as there are hours using only a pointer.
for (int i = 0; i < totalHours; i++)
{
cout << " " << i + 1;
while (ptrSvr <= last)
{
rand_set(ptrSvr);
print(ptrSvr);
ptrSvr++;
}
cout << endl;
}
return 0;
With this being the function for rand_set
void rand_set(int* &ps)
{
*ps = rand() % 10;
}
And this being the function for print.
void print(int* ps)
{
cout << " " << *ps << " ";
}
Once this iterates though, I don't understand how to set the pointer back to the first address in the array so that when i increases, it will print a new row starting at the beginning. Currently, it will only print one row. There's also a catch - I can only use the given pointer to access the array. I cannot use array indices.
Additionally, the highest number randomly generated must be stored in a highestAttempts pointer and when printed, must have a * next to it. This functionality must be included in the rand_set function. I've only gotten it to print a * next to all of them, or it gets printed on the first random number, and on each one if they increase.
Thanks for any advice in advance. I am in a 200 level c++ class, so this should be as simple as possible.
Variables are declared and initialized like so.
void initialize(int ts, int* &ps, int* &pt,
int* &l, int* &ha)
{
for (int i = 0; i < ts; i++)
{
ps[i] = 0;
pt[i] = 0;
l = &ps[i];
}
ha = NULL;
srand(time(NULL));
}
...
// Pointer declarations
int *ptrSvr; // Po
int *ptrTotal; // Po
int *last; // Po
int *highestAttempts; // Po
// Variable declarations
int totalServers; // Va
int totalHours; // Va
int total; // Va
// Prompt user for number of serv
// totalServers and totalHours
cout << "Enter the number of web
cin >> totalServers;
cout << "Enter the number of hour
cin >> totalHours;
// Declares arrays for ptrSvr and
// of total servers
ptrSvr = new int[totalServers];
ptrTotal = new int[totalServers];
if you have something like
int arr [] = {};
then
ptrSvr = arr;
after while loop would reset it. otherwise you have to store the very first value of ptrSvr and reset it after while loop exits

Working with array of structures in C using pointer to pointer

I am trying to learn better how pointer work in C and pointer to pointer to structure things broke my mind. Here I have 3 questions:
If I have a structure and a pointer to pointer **tests to this structure (so this is something like an array) how can I use p to access to array members (the best way)? tests[i]->id fails (example of source is below)
Having that monstrous line with pointers below is something bad to have in the code but I would like to do work with it as well. I think I've mistaken with its template, the output for every next structure's address looks like jumps 32 bytes ahead, while size of structure is only 4 bytes. So in the line I want to (1) take the initial address of the tests top pointer, (2) add to it size of the structure TestCase multiplied by i so it points to correct array element and (3) add offset of the id field of the structure. And after that I will get address where I can write the id value in memory, right? Am I doing this correct?
Why *tests value was changed? Buffer overflow?
struct TestCase{
int id;
};
int main()
{
TestCase ** tests;
cout << "Size of TestCase: " << sizeof(TestCase) << endl;
*tests = (TestCase*)malloc(sizeof(TestCase*)*5);
cout << "*tests = " << *tests << endl;
for(int i = 0; i < 5; i++)
{
//*(int*)(tests+sizeof(TestCase)*i+(int)&(((struct TestCase*)NULL)->id)) = i;
int addr = tests; // address of structures array in memmory;
addr += sizeof(TestCase)*i; //address of current structure;
addr += (int)&(((struct TestCase*)NULL)->id); // Adding id parameter offset in memory to current address
*(int*)addr = i; // setting id for current structure equal to i
cout << (int*)(tests+sizeof(TestCase)*i+(int)&(((struct TestCase*)NULL)->id)) << endl;
}
cout << "*tests = " << *tests << endl;
return 0;
}
Output is:
Size of TestCase: 4
*tests = 0x600048600
0x23ab90
0x23abb0
0x23abd0
0x23abf0
0x23ac10
*tests = 0x600000000
P.S.: Updated cycle code from one monstrous line to step by step actions.
Assuming that you want tests to be an array-of-pointers-to-struct-TestCase with 5 pointers to 5 structs, then you need to
allocate an array of 5 pointers, and
initialize each pointer by allocating memory for the struct
Like this:
#include <stdio.h>
#include <stdlib.h>
struct TestCase
{
int id;
};
int main( void )
{
int i;
struct TestCase **tests;
// allocate memory for an array of 5 pointers
tests = malloc( 5 * sizeof(struct TestCase *) );
if ( tests == NULL )
exit( 1 );
// allocate memory for 5 structures (and save each pointer in the array)
for ( i = 0; i < 5; i++ )
{
tests[i] = malloc( sizeof(struct TestCase) );
if ( tests[i] == NULL )
exit( 1 );
}
// initialize the id in each struct
for ( i = 0; i < 5; i++ )
tests[i]->id = i;
// print the id in each struct
for ( i = 0; i < 5; i++ )
printf( "%d\n", tests[i]->id );
// free memory
for ( i = 0; i < 5; i++ )
free( tests[i] );
free( tests );
return 0;
}
I wasn't able to reproduce the problem described in point 2. Here's the code I tried (which I placed ahead of the code that frees memory)
printf( "%p\n", tests );
for ( i = 0; i < 5; i++ )
{
intptr_t addr = (intptr_t)tests;
addr += sizeof(struct TestCase)*i;
addr += (int)&(((struct TestCase*)NULL)->id);
printf( "%p\n", (void *)addr );
}
The output from the code is
0xc03950
0xc03950
0xc03954
0xc03958
0xc0395c
0xc03960
The address advances by 4 bytes as expected. Note that I changed the type of addr to intptr_t to guarantee that the pointer can be cast properly, but that doesn't effect the math in the subsequent two lines.
In your code tests is triple *, remove the additional * from the malloc line and test[0]->id assignments will work.
If you need a high level access to an offset, assign values as you initially wanted to in question 1. IE - tests[0]->id = 0x3834 , or memcpy for dynamic assignments. ThereĀ“s no need for all those references and casts.
Because tests was reassinged in the first line of your iterator.
Thanks to #user3386109 I was able finally to do everything I wanted. Well, instead of writing to address using creepy formula I am now reading from address using the same creepy formula:
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <stdlib.h>
using namespace std;
struct TestCase{
int ida;
int idb;
};
int main()
{
TestCase ** tests; //create pointer to pointer
cout << "Size of TestCase: " << sizeof(TestCase) << endl;
tests = malloc(sizeof(TestCase*)*5);
if(tests == NULL)
exit(1);
for(int i=0; i< 5; i++)
{
tests[i] = malloc(sizeof(struct TestCase));
if(tests[i] == NULL)
exit(1);
}
cout << "*tests = " << *tests << endl;
for(int i = 0; i < 5; i++)
{
tests[i]->ida = i;
tests[i]->idb = i+6;
cout << std::hex << &(tests[i]->idb) << ": " << *(long*)((long)(long*)(tests[i])+(long)&(((TestCase *)NULL)->idb)) << endl;
}
for(int i=0; i<5; i++)
{
free(tests[i]);
}
cout << "*tests = " << *tests << endl;
free(tests);
return 0;
}
Output:
$ ./a.exe
Size of TestCase: 8
*tests = 0x600048630
0x600048634: 6
0x600048654: 7
0x600048674: 8
0x600048694: 9
0x6000486b4: a
*tests = 0x600048630

Arrays and Pointers as arguments and return values

#include <iostream>
using namespace std;
int getDegree()
{
int degree;
cout << "Enter degree of polynomial" << endl;
cin >> degree;
return degree;
}
int* getPoly(int degree)
{
cout << "Enter coefficients in order of power of x. e.g. for 2 + x + 3x^2, enter 2 then 1 then 3" << endl;
int coeff [degree +1];
for (int i = 0; i <= degree; i++)
{
cin >> coeff[i];
}
return coeff;
}
int* polyder(int p[], int degree)
{
int dp[degree];
for(int i = 0; i < degree; i++)
{
dp[i] = p[i+1] * (i+1);
}
return dp;
}
int main(int argc, const char * argv[])
{
int degree = getDegree();
int p = *getPoly(degree);
int dp = *polyder(&p, degree);
for(int i = 0; i < degree +1; i++)
cout << " " << p[i] << " x^" << i;
cout << endl;
for(int i = 0; i < degree +1; i++)
cout << " " << dp[i] << " x^" << i;
cout << endl;
return 0;
}
I am getting an error during the print statements.
I am not worried about the math involved, just how to pass the arrays between functions/methods.
Can anyone find why this is not working?
I am new to C++, used to Java.
Can anyone find why this is not working?
In C++ variables are destroyed when the scope in which they were declared ends. You return an address of a variable that doesn't exist when the function ends:
int* getPoly(int degree)
{
int coeff [degree +1];
// ...
return coeff;
}
If you wish the variable still exists after the function ends, you have to allocate it using new:
int* getPoly(int degree)
{
int *coeff = new int[degree +1];
// ...
return coeff;
}
And, at the end of your main function (or wherever you don't need the array anymore), call delete[] to deallocate the memory:
int *p = getPoly(degree);
delete[] p;
The Array name is essentially a pointer to the first element of the array (as you can see in the code above, I've declared p as a pointer to int), so you pass them to other functions just by providing their name:
int* polyder(int p[], int degree){/*do something here*/}
// <-- some other code
int *p = getPoly(degree);
int* returnedArray = polyder(p,degree);
First of all, the line
int coeff [degree +1];
is not a valid C++ statement unless 'degree' is a constant, even through some compilers may allow it.
Even if some compiler allowed it, the space for coeff is allocated from the stack and will be invalid after the function returns. Hence, the line
return coeff;
returns an memory location that will be invalid at its usage.
In order to return valid memory function, replace the line
int coeff [degree +1];
by
int* coeff = new int[degree];
You don't need degree+1 items in the array.
Similar changes are needed in the function polyder.
The thing to remember about arrays in C++ is that unlike Java, they are not objects (at least in the way they are in Java). They're simply pointers to a block of allocated memory, and the [] operator simply automatically does the math to move the pointer to the correct location.
When passing arrays between functions, you're basically just passing a pointer. Unless you want to get into some highly complicated and likely too much for your use case code, you should always pass the size of the array along with it to ensure that your indexes always stay in bounds.
And as the other answer points out, you need to ensure that the life cycle of the array lasts as long as you need it to. Simply returning a pointer to an object doesn't keep it alive like returning a reference does in Java.