0
int x=2,y=3,*p;
p = &x;
cout<<p<<"\t"<<*p<<"\n"; //0x6dfef4    2
--p;
cout<<p<<"\t"<<*p<<"\n"; //0x6dfef0    1969648845

why when p is --p previous pointer is another one number . without cout

but when i print address of x and y values is different

int x=2,y=3,*p;
p = &x;
cout<<p<<"\t"<<*p<<"\n"; // 0x6dfef8        2
--p;
cout<<p<<"\t"<<*p<<"\n"; // 0x6dfef4        3
cout<<"Adress x = "<<&x<<"\n" // Adress x = 0x6dfef8;
cout<<"Adress y = "<<&y<<"\n" // Adress y = 0x6dfef4;
faham
  • 17
  • 1
  • 8
  • 9
    `--p;` invokes *undefined behavior*. You cannot legally perform pointer arithmetic on a pointer to a single object. Also you have no idea where variables are being allocated (as that is chosen by the compiler) – UnholySheep Jan 19 '18 at 20:47
  • 3
    I think you want *p-- – Katianie Jan 19 '18 at 20:49
  • [Reading material](https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior) – Silvio Mayolo Jan 19 '18 at 20:50
  • 2
    The other point to consider is that you probably have an *optimizing* compiler. Thus, variables can be eliminated where appropriate. – Deduplicator Jan 19 '18 at 20:52
  • 3
    @UnholySheep: You can. `++p` would have been perfectly fine, though dereferencing afterwards would be bad. – Deduplicator Jan 19 '18 at 20:53
  • @Deduplicator I used to think so as well, but I was recently informed that pointer arithmetic is only defined behavior if the pointer points to an element of an array (see e.g.: https://stackoverflow.com/a/15608422/2878796) – UnholySheep Jan 19 '18 at 21:00
  • 3
    @UnholySheep An object is considered an array with one element. Incrementing a pointer one pass the end of an array is well-defined. – Passer By Jan 19 '18 at 21:02
  • 2
    @UnholySheep - And if you don't believe us, believe [\[expr.unary.op\]/3](http://eel.is/c++draft/expr.unary.op#3.sentence-5). – StoryTeller - Unslander Monica Jan 19 '18 at 21:04
  • Well, I'm learning something new about C++ pointers and UB every day. So many special cases/definitions I never knew about – UnholySheep Jan 19 '18 at 21:07

2 Answers2

3

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.)

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • Your explanation about the different address is obviously wrong. Evidence: The delta is only 4 (ASLR uses page granularity), and OP gave two different sources. – Deduplicator Jan 19 '18 at 21:55
  • @Deduplicator That was an error on my part - I misread the addresses when I was writing up this answer. Though I do maintain that the addresses of those variables might not be the same from run to run. – templatetypedef Jan 20 '18 at 01:18
2

In the first code. By doing --p. The pointer move back to 4 Bytes position (you should compile in 32 bits and integer is 4 bytes size in that case) so adress is 0x6dfef8 - 4 = 0x6dfef4. The value of this memory adress is random 1969648845 because who know what the compiler has put into this adress... certainly nothing.

In the second code, the value of 0x6dfef4 is 3 because compiler should have save the y variable value at this adress (0x6dfef4 should be the adress of y). That is a "random" result depending of compiler/linker, y could be at 0x6dfefc or other adress. When you check the x and y variables adresses with the code:

cout<<"Adress x = "<<&x<<"\n" // Adress x = 0x6dfef8;
cout<<"Adress y = "<<&y<<"\n" // Adress y = 0x6dfef4;

It confirm that x and y are side by side adresses.

If you do the same 'adress printing test in the first code, you should see that y is not at 0x6dfef0 adress.

What is a POINTER

Any variable is located at an adress in the memory and this adress contain a value with a size (some bytes 2 (16bits) , 4 (32 bits) ,8 (64bits)). When the value of this variable is an adresse value, we call this variable a pointer.

I hope this explanation of pointer will help some to understand better. A drawing like this http://www.cplusplus.com/doc/tutorial/pointers/pointer_arithmetics.png help to understand ++ or -- operation.

E.Racineux
  • 88
  • 5