I suspect that you're getting confused about what --p
does. The expression --p
does not mean "decrease the number pointed at by p
."
To see what's going on here, imagine that, initially, you have p
pointing to x
, like this:
+-----------+ +---------+
p | address A | ----> | 2 | x
+-----------+ +---------+
When you write --p
, C++ interprets this to mean "change where p
is pointing so that it looks at the integer in memory just before x
." That looks like this:
+---------+
+--> | ??????? | (not a variable)
+-----------+ | +---------+
p | address B | --+ | 2 | x
+-----------+ +---------+
Notice that p
is now pointing somewhere else in memory, and there's no guarantee that there's actually an int
there. You're essentially reading a garbage value at this point. That's why you see both a new address stored in p
(since you've changed where it's pointing) and a new value for *p
(since you're pulling random bytes from memory). Notice that you are not guaranteed to be pointing to y
when you do this; C++ doesn't make that guarantee.
You also asked why you got different addresses for x
and y
when running the program a second time. C++ doesn't guarantee that across multiple runs of the program, the same variables will end up in the same positions. In fact, many OSes will randomize where variables actually end up being assigned on each run, so that's the expected behavior here.
If you want to change p
to point to y
, just write p = &y;
. That explicitly assigns it to point to p
. Pointer arithmetic is only valid in the context of arrays (with a few technical caveats that aren't worth detailing here.)