Reputation: 17
Below is a sample program I created to play around with pointers.
#include <iostream>
using namespace std;
void addOne(int** ptr);
void addTwo(int*** ptr);
void addThree(int**** ptr);
void addFour(int***** ptr);
int main()
{
int* ptr = nullptr;
int x = 1;
ptr = &x;
cout << "Original value of x: " << *ptr << endl;
addOne(&ptr);
cin.get();
return 0;
}
void addOne(int** ptr)
{
**ptr += 1;
cout << "After adding 1: " << **ptr << endl;
addTwo(&ptr);
}
void addTwo(int*** ptr)
{
***ptr += 2;
cout << "After adding 2: " << ***ptr << endl;
addThree(&ptr);
}
void addThree(int**** ptr)
{
****ptr += 3;
cout << "After adding 3: " << ****ptr << endl;
addFour(&ptr);
}
void addFour(int***** ptr)
{
*****ptr += 4;
cout << "After adding 4: " << *****ptr << endl;
}
The program above will give me the following output:
Original value of x: 1
After adding 1: 2
After adding 2: 4
After adding 3: 7
After adding 4: 11
Now focus on the addFour function:
void addFour(int***** ptr)
{
*****ptr += 4;
cout << "After adding 4: " << *****ptr << endl;
}
Now what I did was I reduced the number of *s in the addFour function by doing this:
void addFour(int***** ptr)
{
****ptr += 4;
cout << "After adding 4: " << ****ptr << endl;
}
When I did the above code, it gave me the following output:
Original value of x: 1
After adding 1: 2
After adding 2: 4
After adding 3: 7
After adding 4: 010EFDE0
My question then is, what is the following statements doing since I reduced the number of *s:
****ptr += 4;
cout << "After adding 4: " << ****ptr << endl;
Can someone please explain this for me?
Upvotes: 0
Views: 4525
Reputation: 534
// if you want to understand pointers this is my fave example
struct block
{
int data;
struct block *next_block;
};
struct block *block_head = NULL;
add_block(int n) /* add n in the sorted position */
{
struct block *new, *prev = NULL, *bp = block_head;
new = malloc(sizeof(struct block));
new->data = n;
while(bp != NULL)
if(bp->data > n)
{
prev = bp;
bp = bp->next_block;
}
else
{
if(prev == NULL)
{
new->next_block = bp;
block_head = new;
}
else
{
new->next_block = bp;
prev->next_block = new;
}
if(block_head == NULL)
block_head = new;
else
{
prev->next_block = new;
new->next_block = NULL;
}
}
// the above is how you usually do a linked list but it's messy and ugly
// not elegant
// the elegant way to do this is with a double pointer
add_block(int n) /* add n in the sorted position */
{
struct block *new, **bp = &block_head;
new = malloc(sizeof(struct block));
new->data = n;
while(*bp != NULL)
if((*bp)->data > n)
bp = &((*bp)->next_block);
else
break;
new->next_block = *bp;
*bp = new;
}
// if you can understand the elegant version, you probably got pointers down cold.
Upvotes: 0
Reputation: 385108
You reduced the dereferencing in addFour
to four levels, but the function still takes an int*****
.
Most of your code is irrelevant and can be reduced to something like this:
int x = 1;
cout << "Original value of x: " << *&x << endl;
x += 1;
cout << "After adding 1: " << **&&x << endl;
x += 2;
cout << "After adding 2: " << ***&&&x << endl;
x += 3;
cout << "After adding 3: " << ****&&&&x << endl;
x += 4;
cout << "After adding 4: " << *****&&&&&x << endl;
So far your dereference and address-of operations cancel out. But then you're asking what this is:
cout << "After adding 4: " << ****&&&&&x << endl;
Quite simply, you have not performed the final dereference so you're left with &x
, not x
.
And &x
is a pointer. In the example above, you'd be seeing the address of x
in memory, given in hexadecimal notation. In your case, your ptr
has an unspecified value because pointer arithmetic out of bounds of an object has undefined behaviour, but in practice you're printing the value of the address of x
plus sizeof(int)
.
Upvotes: 3
Reputation: 12037
Trying to visualize this graphically, you have:
P -> P -> P -> P -> P -> X
X
is the value, P
are pointers.
Every time you write &
, you move to the left, and every time you write *
, you move to the right.
So if you have &&&&&x
, and you increment ****x
, you do this:
P -> P -> P -> P -> P -> X
\
> ?
You moved four levels to the right, and incremented the pointer there, which now points to a memory location after X.
Then you print ****x
, which is a pointer, because you moved four levels to the right.
Upvotes: 1
Reputation: 36391
addOne
receives the address of ptr
that points to x
and store it into a local variable ptr
.
addTwo
receives the address of addOne::ptr
and store it in its local ptr
variable.
addThree
receives the address of addTwo::ptr
and store it in its local ptr
variable.
addFour
receives the address of addThree::ptr
and store it in its local ptr
variable. Thus in addFour
(second version):
*ptr
is addThree::ptr
,**ptr
is addTwo::ptr
,***ptr
is addOne::ptr
and****ptr
is main::ptr
.You then increment a pointer to int by 4, thus calculating the address of the fourth int starting from the address of x
, and then print that address.
Of course, in the first version *****ptr
is main::x
, and you then increment int x
by 4.
Upvotes: 1