Reputation: 67
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
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
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
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
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