Address of the Pointer pointing to the first element - c++

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;

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.

Why does this pointer show the last element?

Please explain to me how the b pointer shows the last element.
Every time, it prints out the last element, no matter how long the array is. If you use *b alone in cout, it shows a number out of array.
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int a[] = {1,2,3,4,5,6,7,8,9,10,11};
int *b =(int*) (&a+1);
cout << *(b-1) << endl;
return 0;
}
This expression
&a+1
has the type int ( * )[11] and points to the memory after the last element of the array a.
In this declaration
int *b =(int*) (&a+1);
you interpreted the expression as having the pointer type int * that points to after the last element of the array a. Instead you could write
int *b = a + 11;
So the expression
b - 1
points to the last element of the array a.
Thus you may imagine the expression *( b - 1 ) the following way
*( a + 11 - 1 ) => *( a + 10 ) => a[10]
Per pointer arithmetic rules, incrementing/decrementing a pointer by N elements will adjust the value of the pointer by N * sizeof(T) bytes, where T is the dereferenced type of the pointer.
&a is a pointer to the array itself, which has a type of int[11], so you have a pointer of type int(*)[11] to the beginning of the array. Lets call this A1 in the diagram below.
Adding +1 to that pointer will advance it by sizeof(int[11]) (aka sizeof(int)*11) bytes, thus producing a new int(*)[11] pointer to the memory address immediately following the entire array. Let's call this A2 in the diagram.
You are then type-casting that new pointer, so now you have a pointer of type int* to the end of the array. This is the memory address you are assigning to your int *b pointer variable. Lets call this B1 in the diagram below.
Subtracting -1 from that pointer will reduce it by sizeof(int) bytes, thus producing a new int* pointer to the memory address of the last int element in the array. Lets call this B2 in the diagram below.
So, when you dereference b to print the int that it is pointing at, you are printing the value of the last int in the array. If you don't decrement b, it is pointing past the end of the array, and you have undefined behavior. You might just print out random garbage, or you might crash your app. Anything could happen.
---------------------------------------------------------------------
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
---------------------------------------------------------------------
^ ^ ^
| | |
|_A1 --------------------------------------------------------|----->|_A2
+1 | |
|_B2 <-|_B1
-1

Array of Pointers Pointing to an unknown location

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.

what is pointer past the end of an object means?

In C++ Primer, Chapter 2, "Variables and Basic Types", it says:
it is possible for a pointer to an object and a pointer one past the end of a different object to hold the same address.
I'm not a native speaker, and I think that's why I'm a bit confused by the sentence "a pointer one past the end of an object". Would anyone one tell me what it means please?
It means that after
int a[] = { 1, 2 };
float b;
it's possible that (void *) &a[2] == (void *) &b may compare as true.
&a[2] (or equivalently, a+2) is a pointer just past the end of a, because the array only contains elements with indices 0 and 1.
Normally, out-of-range array indices are completely invalid (accessing a[2] is not allowed, nor is even computing &a[3]), but there is a special exception for computing the address just past the end of an array, because as it turned out, that is quite useful, for example when iterating over an array and you need an end value to know when to stop the loop.
Suppose you have an array, int foo[5] = {1,2,3,4,5};. It's laid out in memory like this:
-----------
|1|2|3|4|5|
-----------
It's legal to have a pointer that points to any member of the array; but it's also legal for a pointer to point one past the end of the array (usually to signal that it has reached the end of the array when doing an STL algorithm using iterators) - although it isn't legal to dereference that pointer. Like so:
-------------
|1|2|3|4|5|?|
-------------
^ ^
| |
p q
p is a pointer into the array; q is a pointer one-past-the-end.
Now, suppose you also have an array const char bar[3] = "Hi";. It's possible that the two arrays have been allocated next to each other in memory, like so:
<--foo---> <-bar->
-----------------
|1|2|3|4|5|H|i|0|
-----------------
^ ^
| |
p q
Then q is both a one-past-the-end for foo, and also pointing to the physical location for bar[0].
"one past" means "+1 operation on the pointer". The following code generates:
0x7ffffcf6a848
0x7ffffcf6a84c
0x7ffffcf6a84c
As you can see, the address of "one past a", i.e., &a + 1 is the same as &b.
int a = 2;
int b = 3;
cout<< &a << endl << &a + 1 << endl << &b <<endl;

Increment operator on pointer of array errors?

I'm trying something very simple, well supposed to be simple but it somehow is messing with me...
I am trying to understand the effect of ++ on arrays when treated as pointers and pointers when treated as arrays.
So,
int main()
{
int a[4] = { 1, 4, 7, 9 };
*a = 3;
*(a+1) = 4;
*++a = 4; //compiler error
}
1: So at *(a+1)=4 we set a[1]=4; //Happy
But when *++a = 4;, I'd expect pointer a to be incremented one since ++ is precedent to * and then * kicks in and we make it equal to 4. But this code just does not work... Why is that?
Another problem:
int main()
{
int* p = (int *)malloc(8);
*p = 5;
printf("%d", p[0]);
*++p = 9; //now this works!
printf("%d", p[1]); //garbage
printf("%d", p[0]); //prints 9
}
2: Now *++p = 9; works fine but it's not really behaving like an array. How are two different? This is just incrementing p, and making it equal to 9. If I print p[0], it now prints 9 and I see that though can't access it via p[0] anymore, *(p-1) shows 5 is still there. So indexing a pointer with [0], where exactly does it point to? What has changed?
Thanks a lot all experts!
The array names is not modifiable lvalue so operation ++ is not applied hence ++a that try to modify a is compilation time error (where a is array name).
Note *(a + 1) and *a++ are not same, a + 1 is a valid instruction as it just add 1 but doesn't modify a itself, Whereas ++a (that is equvilent to a = a + 1) try to modify a hence error.
Note 'array names' are not pointer. Pointers are variable but array names are not. Of-course when you assign array name to a pointer then in most expressions array names decays into address of first element. e.g.
int *p = a;
Note p points to first element of array (a[0]).
Read some exceptions where array name not decaying into a pointer to first element?
An expression a[i] is equivalent to *(a + i), where a can be either a pointer or an array name. Hence in your second example p[i] is valid expression.
Additionally, *++p is valid because because p is a pointer (a variable) in second code example.
int a[4] = { 1, 4, 7, 9 };
int *pa=a;
There is one difference between an array name and a pointer that must be kept in mind. A pointer is a variable, sopa=a and pa++ are legal. But an array name is not a
variable; constructions like a=pa and a++ are illegal
int* p = (int *)malloc(8);
Don't cast result of malloc()
Use index with pointer
p[1]=9; // p[1]==*(p+1)