73memedream
73memedream

Reputation: 67

Pointer Arithmetic Incrementing post/pre-fix

I'm having trouble following through the logic of a specific piece of code below.

int i[] = { 21, 4, -17, 45 };

int* i_ptr = i;

std::cout << (*i_ptr)++ << std::endl;   // 21

std::cout << *i_ptr << std::endl;       // 22

std::cout << *i_ptr++ << std::endl;     // 22

std::cout << *(i_ptr - 1) << std::endl; // 22

std::cout << *i_ptr << std::endl;       // 4

std::cout << ++*i_ptr << std::endl;     // 5

std::cout << *++i_ptr << std::endl;     // -17

system("pause");

My problem is how did this bit of code go from 22...

std::cout << *(i_ptr - 1) << std::endl; // 22

To 4.

std::cout << *i_ptr << std::endl;       // 4

And then to 5.

std::cout << ++*i_ptr << std::endl;     // 5

When I first went through this code, I thought that 22 was just gonna goes from 22 to 21. I understand that it has to do with C++ operator precedence , but this makes no sense to me.

Upvotes: 2

Views: 138

Answers (4)

Some programmer dude
Some programmer dude

Reputation: 409412

The expression *i_ptr++ increments the pointer. It makes it point to the second element of the array (with the value 4).

That of course means that i_ptr - 1 must point to the element before where i_ptr is currently pointing, which is the first element (with the value 22).

And remember, for any pointer or array p and index i, the expressions p[i] and *(p + 1) are exactly equal.


Another way to see it, you start out with

+-----+-----+-----+-----+
|  21 |   4 | -17 |  45 |
+-----+-----+-----+-----+
^
|
i_ptr

You then do (*i_ptr)++ which increments the value where i_ptr is pointing:

+-----+-----+-----+-----+
|  22 |   4 | -17 |  45 |
+-----+-----+-----+-----+
^
|
i_ptr

Then you do *i_ptr++ which first dereference the old value of i_ptr (which results in 22) and then increment the pointer:

+-----+-----+-----+-----+
|  22 |   4 | -17 |  45 |
+-----+-----+-----+-----+
      ^
      |
      i_ptr

And now you do basically i_ptr[-1]:

+-----+-----+-----+-----+
|  22 |   4 | -17 |  45 |
+-----+-----+-----+-----+
^     ^
|     |
|     i_ptr
|
i_ptr - 1

Negative indexes are okay and well defined, as long as they don't go out of bounds.

Upvotes: 1

templatetypedef
templatetypedef

Reputation: 373112

This has to do with these three lines:

std::cout << *i_ptr++ << std::endl;     // 22
std::court << *(i_ptr - 1) << std::endl; // 22
std::cout << *i_ptr << std::endl;       // 4

Here’s what happens:

std::cout << *i_ptr++ << std::endl;     // 22

Here, this is interpreted as *(i_ptr++), which means “advance ptr forward to point to the next element, then hand back a pointer to where i_ptr used to be pointing and derference that.” In other words, after this line finishes executing, the pointer ptr is pointing at the element 4, but the line prints 22 because that’s where ptr used to be pointing. This is important since it means that we’ve changed where we’re looking, even though the output doesn’t immediately suggest this.

Let’s look at the next line:

std::cout << *(i_ptr - 1) << std::endl; // 22

This says “print out the element one spot before where i_ptr is looking.” Remember that at this point in time i_ptr is looking at 4, so by looking one element back in the list we see the value 22.

Finally, we do this:

std::cout << *i_ptr << std::endl;       // 4

This says “print out whatever i_ptr is looking at.” Since we’re looking at 4 - and have been for a while - that’s what we see here.

Upvotes: 0

mch
mch

Reputation: 9814

std::cout << (*i_ptr)++ << std::endl;   // 21
//i_ptr points to i[0], which is increased from 21 to 22

std::cout << *i_ptr << std::endl;       // 22
//prints i[0], which is 22

std::cout << *i_ptr++ << std::endl;     // 22
//prints i[0] and increments i_ptr to point to i[1]

std::cout << *(i_ptr - 1) << std::endl; // 22
//prints i[0], i_ptr points to i[1], so i_ptr - 1 points to i[0]

std::cout << *i_ptr << std::endl;       // 4
//prints i[1], which is 4

std::cout << ++*i_ptr << std::endl;     // 5
//prints the incremented i[1], which was 4 and is 5 now

std::cout << *++i_ptr << std::endl;     // -17
//increment i_ptr to point to i[2] and prints the value

Upvotes: 5

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 123114

Already after this line

std::cout << *i_ptr++ << std::endl;     // 22

i_ptr points to the 4. Thus in the next line when you print one element before you get again 22:

std::cout << *(i_ptr - 1) << std::endl; // 22

and now i_ptr still points to the 4:

std::cout << *i_ptr << std::endl;       // 4

Upvotes: 0

Related Questions