Array of Pointers Pointing to an unknown location - c++

I was practicing with array of pointers.
i wrote a simple code.
#include<iostream>
using namespace std;
int main(){
int a[3]={1,2,3};
int *b[3];
for(int i=0; i<3; i++){
b[i] = &a[i];
}
cout<<b; //This gives a confusing output
cout<<endl;
for(int i=0; i<3; i++){
cout<<b[i];
cout<<endl;
}
}
and Output is
0x6ffe10
0x6ffe30
0x6ffe34
0x6ffe38
Now I don't understand where the b pointing.
I know this sounds weird but i wanna know.
where the b pointer pointing.
The b[0], b[1], b[2] gives expected result.

b is an array of pointers to int. It's address is the address of the first pointer.
The first pointer b[0] is assigned the address of element a[0] (so b[0] points to 1).
b[1] is assigned the address of a[1] (so b[1] points to 2)
b[2] is assigned the address of a[2] (so b[2] points to 3)
In each case the pointer in the b array holds the address of the corresponding element within a. So if there are any changes made to the elements of a after your loop assigning the address in a to b, the value held in the memory location pointed to by the element of b will change, but the address for that value held by b will remain unchanged.

When b is passed to cout's << operator, it decays into a pointer; hence as far as the printing function is concerned, printing out b is the same as printing out &b[0].
Therefore, cout << b; prints out the address of the first pointer in the b[3] array. (Note that the address of the pointer is not the same thing as the address the pointer is pointing to! That can be a source of confusion -- just keep in mind that a pointer-variable is a variable as well, and like any other variable, it has its own unique location in memory, which is distinct from the location it is pointing at)

b is an array of pointers to int which is a local variable on the stack.
Its address does not depend on what individual elements of its array are assigned to.
If you print its value before the for loop (where you assign values to its members), you will see that it is the same as the value printed after the for loop.
See live demo here.
Pictorially:

b Memory adress of the whole array.

Related

Why does (*p)[2] and *(p[2]) give the same result in array of pointers?

In the following c/c++ code,
int main()
{
int a[3] = {11, 22, 33};
int *p[3];
p[0] = &a[0];
p[1] = &a[1];
p[2] = &a[2];
printf("(*p)[2] = %d\n",(*p)[2]);
printf("*(p[2]) = %d\n",*(p[2]));
return 0;
}
It turns out that (*p)[2] = *(p[2]) = a[2].
So, I understand that with int *p[3];, I am creating an array of three pointers, and with the subsequent three lines after int *p[3];, I am putting the address of a[0] into p[0], address of a[1] into p[1], and address of a[2] into p[2].
Then, with *(p[2]), I am retrieving the variable pointed by the address stored in p[2], which makes *(p[2]) = a[2]. I have two questions regarding this simple code:
how to understand that (*p)[2] also equals a[2]?
If p is no longer defined as an array of pointers to int variables, but an array of pointers to vectors of type int (std::vector in C++), does the equality (*p)[2] = *(p[2]) still hold?
*p is the same as p[0], which is a pointer to a[0]. So (*p)[2] is a[2].
p[2] is a pointer to a[2], so *(a[2]) is also a[2].
Nothing magical going on here. It's just the way you have set up your pointers.
It's because your array of pointers is an array of pointers that all point within the same array.
(*p)[2] effectively expands to (&a[0])[2] (because &a[0] is in p[0]), reading the second element of a by starting from &a[0] and skipping two elements.
*(p[2]) effectively expands to *(&a[2]) (because &a[2] is in p[2]), which is equivalent to (&a[2])[0], reading the second element of a by starting from &a[2] and not skipping any elements.
Either way, you end up reading the value from a[2], the only question is whether you're dereferencing a pointer that doesn't point to a[2] at an offset, or dereferencing a precalculated pointer to a[2] without an offset. You could get the same result with p[1][1] as well, it just doesn't look quite as symmetrical with the other two use cases.
Regardless, all of this works because the definition of p is weird; it's a toy to illustrate how pointers and indexing work.

How a double pointer fetch the value from a single poiner

An array is right now pointed by a single pointer. And a double pointer is pointing to the single pointer. I am trying to fetch the value of the array using this double pointer. As far I have only fetched the first index value of the array by the double pointer.
I know that if I dereference (*ptr2) a double pointer then it will give the address where the first pointer is pointed (ptr1) which means the first index address of the array(&array[0]).
#include <iostream>
using namespace std;
int main(){
int array[5]{15,25,35,45,55};
int* ptr1;
int** ptr2;
ptr1 = &array[0];
ptr2 = &ptr1;
In the following for loop, I have tried to print the value of array using pointer ptr1.
for(int i =0; i<5; i++){
cout<<"the value: "<<*(ptr1+i)<<" lives at "<<ptr1+i<<" address\n";
}
cout<<"\n";
In the following for loop I have tried to check *ptr2 is all-time giving me address pointed by ptr1 or not. But I have found that it only works/same for the first index then it is (*ptr2) giving me a different address
for(int j=0; j<5; j++){
cout<<"adress of array: "<<&array[j]<<" , ptr1: "<<(ptr1+j)<<" , val of ptr2: "<<*(ptr2+j)<<endl;
}
cout<<"\n";
return 0;
}
While I have tried to fetch the value from ptr2 by using **ptr2+i using a for loop it continues only for 2 times. First-time correct value which is obvious as I am seeing the address of array[0] and *(ptr2+0) are same. Second-time garbage value and then Segmentation fault (core dumped).
One guess came in my mind that ptr1 and ptr2 both are int type but one is pointing to a variable and another is to a pointer. So maybe there is a memory allocation concept arises from the very beginning which I am skipped.
Is there any way where I can fetch the value of the array using the mentioned structure?
ptr2 is pointing at ptr1. (ptr2+j), when j is not 0, is an address you haven't allocated so dereferencing it (*(ptr2+j)) makes your program have undefined behavior and getting a Segmentation fault is one possible outcome.
You should dereference it first, then index: (*ptr2)[j] or *((*ptr2)+j) if you will.
Your reasoning is close, but you did not apply it well.
I know that if I dereference (*ptr2) a double pointer then it will give the address where the first pointer is pointed (ptr1)
In other words, *ptr2 is a synonym for ptr1. So any place you see ptr1 (after assigning ptr2 = &ptr1) you can substitute in *ptr2. Even better, substitute in (*ptr2) to avoid interference from operators with a higher precedence than de-reference. Let's take an example:
for(int i =0; i<5; i++){
cout<<"the value: "<<*(ptr1+i)<<" lives at "<<ptr1+i<<" address\n";
}
cout<<"\n";
Now do a simple find-and-replace. Replace ptr1 with (*ptr2). Don't try to adjust anything; once you've decided to do this, the process is mindless.
for(int i =0; i<5; i++){
cout<<"the value: "<<*((*ptr2)+i)<<" lives at "<<(*ptr2)+i<<" address\n";
}
cout<<"\n";
This is almost what you tried in your loop, except you used *(ptr2+j) instead of (*ptr2)+i. We can ignore the change from i to j, but those parentheses are significant. You changed the order of operations, which is comparable to using 3(1+4) instead of (3×1)+4. It shouldn't be surprising that 15 does not work where 7 is needed, and similarly adding j before de-referencing does not work where the de-reference needs to be done first.
Note: Since de-reference has a higher precedence than addition, the parentheses around *ptr2 could be dropped from this particular example. That is, *ptr2+i and *(*ptr2+i) would also work.
Note: This question can serve as a demonstration of why it's often wise to avoid pointers-to-pointer.

Address of the Pointer pointing to the first element

In http://www.fredosaurus.com/notes-cpp/arrayptr/array-diagrams.html website, it states that
Pointers hold the memory address of other data and are represented by a black disk with an arrow pointing to the data it references.
For example,
int a[5]; // Allocates memory for 5 ints.
. . .
a[0] = 1;
for (int i=1; i<5; i++) {
a[i] = a[i-1] * 2;
}
would result in.
My question is how can I print the address of the pointer pointing to the array?
I know that &a or &a[0] gives us the address of the first element. But how can I access the pointer pointing the array?
An array and a pointer are not the same thing. What the memory really looks like is this:
a
-------
| 1 | a[0]
-------
| 2 | a[1]
-------
| 4 | a[2]
-------
| 8 | a[3]
-------
| 16 | a[4]
-------
So if you were to print a and &a, you would see that they print the same value.
If the array is on the stack as it would be in your example code then the image below is a more accurate representation of how the memory would be laid out. I've also added an additional pointer to hopefully add some clarification.
int a[5];
a[0] = 1;
for (int i=1; i<5; i++)
a[i] = a[i-1] * 2;
int* b = a;
It may be easier to think of the [] notation of defining an array as a little syntactic sugar. When calling functions and passing in a the function will be called with the address of a[0] being passed in.
When passing b to a function it's the value that will be passed in, which is the address of a.
You can have lots of pointers pointing to a[0].
Just as for a pointer to the array, create a pointer variable pointing to a[0] and then take a pointer to it. You will have one pointer to one pointer pointing to the array.
I know that &a or &a[0] gives us the address of the first element.
Technically. &a is in fact the address of the array itself. It just has the same value as address of the first element. But note that the type of the expression is different. &a is a int (*)[5] (pointer to an array of 5 integers), while &a[0] is a int* (pointer to an integer).
My question is how can I print the address of the pointer pointing to the array?
First step is to have a pointer. You don't have any pointer variables in your example. An array is not a pointer. The sentence "The actual array variable, a in this example, is a pointer to the memory for all of its elements." of the page is very misleading, as an array is not a pointer object. The drawn diagram is not correct for the program.
Here is a program that is correct according to the diagram:
int array[5]; // Allocates memory for 5 ints.
int* a = array; // a pointer to the first element of the array
a[0] = 1;
for (int i=1; i<5; i++) {
a[i] = a[i-1] * 2;
}
Here we actually have a pointer. Now you can print the address of the pointer:
std::cout << &a;

Why is the result of using `int (*p)[5]` so confusing?

I know that int (*p)[5] means a pointer which points to an array of 5 ints.
So I code this program below:
#include <iostream>
using namespace std;
int main()
{
int a[5]={0,1,2,3,4};
int (*q)[5]=&a;
cout<<a<<endl;
cout<<q<<endl;
cout<<*q<<endl;
cout<<**q<<endl;
return 0;
}
On my machine the result is:
0xbfad3608
0xbfad3608 //?__?
0xbfad3608
0
I can understand that *q means the address of a[0] and **q means the value of a[0], but why does q have the same value as a and *q? In my poor mind, it should be the address of them! I'm totally confused. Somebody please help me. Please!
Look at it this way:
q == &a
*q == a
**q == *a
You didn't try printing &a. If you do, you'll see that it has the same value as a. Since &a == a, and q == &a, and *q == a, by transitivity q == *q.
If you want to know why &a == a, check out Why is address of an array variable the same as itself?
q and &a are pointers to the array.
*q and a are "the array". But you can't really pass an array to a function (and std::ostream::operator<< is a function); you really pass a pointer to the first element, which is created implicitly (called pointer decay). So *q and a become pointers to the first element of the array.
The beginning of the array is at the same location in memory that the array is, trivially. Since none of the pointers involved are pointers-to-char (which are handled specially so that string literals will work as expected), the addresses just get printed out.
That because array is automatically converted to a pointer, which just has the value of the address of the array. So when you are trying to print print the array using <<a or <<*q, you are in fact printing its address.

What does (int **array;) create?

I want to know what is happening in memory when you declare:
int **array;
If I am not mistaken...
You have a multidimensional array arr[i][j] and
**arr addresses to arr[0][0]
*((*arr)+1) addresses to arr[0][1]
*(*(arr+1)+1) addresses to arr[1][1]
Sample code in C++
#include <iostream>
using namespace std;
int main()
{
int **arr;
arr = new int*[5];
for(int i = 0; i < 5; i++)
arr[i] = new int[5];
arr[0][1] = 1;
cout << *((*arr)+1); // prints 1
cout << arr[0][1] = 1; // prints 1
}
It creates a variable to store a pointer to an int pointer.
The compiler reserves four bytes (on a 32bit system, eight bytes on 64bit) to store a pointer (that would point to another pointer, that would point to an int). No further memory allocation is done, it is left to the programmer to actually set the pointer to point to some other memory location where the int*/array/... is stored.
You're declaring a pointer variable, so you're allocating enough space for one memory address (depends on your platform/compiler/etc.)
The type system will ensure that the only addresses you assign into it contain other memory addresses, and that these addresses represent the actual address of an integer variable.
To use your pointer-to-pointer, you dereference it once (to get the address that actually points to the integer), and then a second time (to get the actual integer).
You can bypass the type system by explicitly casting to something else (e.g., i=&pDouble) but that is not recommended unless you're sure you know what you're doing.
If you have a two-dimensional array, you can think of it conceptually as one single-dimensional array of single-dimensional arrays representing rows. The first level of indirection would be to pick the row, and the other one to pick the cell in the row.
It's a pointer to an int pointer. This is often used to declare a 2D array, in which case each int pointer is an array and the double pointer is an array of arrays.