An exotic pointer...

P

Patrick6

Hello everyone,

I found something weird happening with a pointer:

Take the following code:

int x=0, n=10, *px=&x, *py=NULL;

printf ("BEFORE: valeur de px = %p et py = %p\n\n", px, py);
*px++=n;
printf ("AFTER : valeur de px = %p et py = %p \n", px, py);

It gives the following result, quite clear, with px becoming px+1 :
BEFORE: valeur de px = 0012FF78 et py = 00000000
AFTER : valeur de px = 0012FF7C et py = 00000000

Everything will stay that way (I mean, normal), should I replace
*px++=n by anything that crosses my mind, like:
*px++; or *++px; (!) or simply px++; or ++px;

But if I do: *++px=n instead, I get the amazing output:
BEFORE: valeur de px = 0012FF78 et py = 00000000
AFTER : valeur de px = 0012FF7C et py = 0000000A <====== (here)

where the value of the py pointer (which has nothing to do with px in
the first place!) has changed.

What is this?

Anyone having any opinion will be quite welcomed, except to say that I
am like the pointer py.
Compiler Microsoft C++ Visual Studio 97 under W2K.
 
M

Mike Wahler

Patrick6 said:
Hello everyone,

I found something weird happening with a pointer:

Take the following code:

int x=0, n=10, *px=&x, *py=NULL;

printf ("BEFORE: valeur de px = %p et py = %p\n\n", px, py);
*px++=n;
printf ("AFTER : valeur de px = %p et py = %p \n", px, py);

It gives the following result, quite clear, with px becoming px+1 :
BEFORE: valeur de px = 0012FF78 et py = 00000000
AFTER : valeur de px = 0012FF7C et py = 00000000

Everything will stay that way (I mean, normal), should I replace
*px++=n by anything that crosses my mind, like:
*px++; or *++px; (!) or simply px++; or ++px;

But if I do: *++px=n instead, I get the amazing output:

Not 'amazing' at all. See below.
BEFORE: valeur de px = 0012FF78 et py = 00000000
AFTER : valeur de px = 0012FF7C et py = 0000000A <====== (here)

where the value of the py pointer (which has nothing to do with px in
the first place!) has changed.

What is this?

It's called 'undefined behavior'. After initialization, 'px'
contains a valid address. After incrementing, 'px' no longer
contains a valid address. You then try to dereference this
invalid pointer value. Behavior is undefined.
Anyone having any opinion will be quite welcomed, except to say that I
am like the pointer py.

See above. However, I must ask why you feel the need to increment
the pointer at all. Don't make the error of believing that objects
declared contiguously in source code would result in contiguous storage
of those objects in memory. This is not guaranteed, and is often
not the case.
Compiler Microsoft C++ Visual Studio 97 under W2K.

Doesn't matter the compiler. You've violated the language rules.
In this particular case, it appears that the result was the corruption
of the value of the object 'py'. But according to the language,
*anything* could have happened, from 'seeming to work', to what
you've seen, to a crash, or anything (or nothing) in between.



-Mike
 
A

Andrey Tarasevich

Patrick6 said:
I found something weird happening with a pointer:

Take the following code:

int x=0, n=10, *px=&x, *py=NULL;

printf ("BEFORE: valeur de px = %p et py = %p\n\n", px, py);
*px++=n;
printf ("AFTER : valeur de px = %p et py = %p \n", px, py);

It gives the following result, quite clear, with px becoming px+1 :
BEFORE: valeur de px = 0012FF78 et py = 00000000
AFTER : valeur de px = 0012FF7C et py = 00000000
OK.

Everything will stay that way (I mean, normal), should I replace
*px++=n by anything that crosses my mind, like:
*px++; or *++px; (!) or simply px++; or ++px;

Well, this is not exactly the same, since you are modifying the pointer
(operator '++'), dereferencing it (operator '*'), but not assigning
anything to the result of the dereference.

However, doing '*++px' is illegal. The result of '++px' no longer points
to 'x' object. It points to memory right after 'x' object. It is legal
to create such a pointer, but attempts to dereference it lead to
undefined behavior.
But if I do: *++px=n instead, I get the amazing output:
BEFORE: valeur de px = 0012FF78 et py = 00000000
AFTER : valeur de px = 0012FF7C et py = 0000000A <====== (here)

That's what I'm talking about. The result of '++px' points to a location
in memory right after 'x' object. Attempts to dereference this pointer
lead to undefined behavior (you are taking it even on step further - you
are trying to modify the memory pointed by the resultant pointer). Your
"amazing output" is nothing more than one possible manifestation of that
undefined behavior.
where the value of the py pointer (which has nothing to do with px in
the first place!) has changed.

Anything can happen. The program might crash. In this case an unrelated
pointer got modified. Undefined behavior is undefined behavior.
 
R

Raymond Martineau

Take the following code:

int x=0, n=10, *px=&x, *py=NULL;
....

Everything will stay that way (I mean, normal), should I replace
*px++=n by anything that crosses my mind, like:
*px++; or *++px; (!) or simply px++; or ++px;

*++px is undefined behaviour. In addition, there is no need to be
incrementing the px pointer anyway, since it only references a single
variable.
But if I do: *++px=n instead, I get the amazing output:
BEFORE: valeur de px = 0012FF78 et py = 00000000
AFTER : valeur de px = 0012FF7C et py = 0000000A <====== (here)

That's the result of undefined behaviour. If you increment a pointer past
the bounds of an array (or in this case, a single variable), it can modify
anything - including variables that appear to be unrelated.
 
T

thesagerat

I found something weird happening with a pointer:

Well...not so wierd really.
int x=0, n=10, *px=&x, *py=NULL;
[...]
But if I do: *++px=n instead, I get the amazing output:
BEFORE: valeur de px = 0012FF78 et py = 00000000
AFTER : valeur de px = 0012FF7C et py = 0000000A <====== (here)

where the value of the py pointer (which has nothing to do with px in
the first place!) has changed.

What is this?

Well let us look at what your variables look like in memory

address value

0012FF74 10 //n
0012FF78 0 //x
0012FF7C 0 //py
0012FF80 0012FF78 //px

When you do *px++ = n, then what happens is first *px = n:

0012FF74 10 //n
0012FF78 10 //x
0012FF7C 0 //py
0012FF80 0012FF78 //px

then px is incremented:

0012FF74 10 //n
0012FF78 10 //x
0012FF7C 0 //py
0012FF80 0012FF7C //px

Getting the result you first saw.
Now if we try the second example, first px is incremented:

0012FF74 10 //n
0012FF78 0 //x
0012FF7C 0 //py
0012FF80 0012FF7C //px

px is moved up to point to the next 32-bit value, which just happens to
be py... Then we set *px = n:

0012FF74 10 //n
0012FF78 0 //x
0012FF7C 10 //py
0012FF80 0012FF7C //px

And there we go.

But don't ever rely on this happening, as the way your variables are
arranged in memory may be up to the compiler and could change.

-Chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top