An exotic pointer...

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Patrick6

    #1

    An exotic pointer...

    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.

  • Mike Wahler

    #2
    Re: An exotic pointer...


    "Patrick6" <patrick.couran t@club-internet.fr> wrote in message
    news:1102987562 .094586.167520@ z14g2000cwz.goo glegroups.com.. .[color=blue]
    > 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:[/color]

    Not 'amazing' at all. See below.
    [color=blue]
    > 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?[/color]

    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.
    [color=blue]
    >
    > Anyone having any opinion will be quite welcomed, except to say that I
    > am like the pointer py.[/color]

    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.
    [color=blue]
    > Compiler Microsoft C++ Visual Studio 97 under W2K.[/color]

    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


    Comment

    • Andrey Tarasevich

      #3
      Re: An exotic pointer...

      Patrick6 wrote:[color=blue]
      >
      > 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[/color]

      OK.
      [color=blue]
      > 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;[/color]

      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.
      [color=blue]
      > 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)[/color]

      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.
      [color=blue]
      > where the value of the py pointer (which has nothing to do with px in
      > the first place!) has changed.[/color]

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

      --
      Best regards,
      Andrey Tarasevich

      Comment

      • Raymond Martineau

        #4
        Re: An exotic pointer...

        On 13 Dec 2004 17:26:02 -0800, "Patrick6"
        <patrick.couran t@club-internet.fr> wrote:
        [color=blue]
        >Take the following code:
        >
        >int x=0, n=10, *px=&x, *py=NULL;
        >[/color]
        ....[color=blue]
        >
        >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;[/color]

        *++px is undefined behaviour. In addition, there is no need to be
        incrementing the px pointer anyway, since it only references a single
        variable.
        [color=blue]
        >
        >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)[/color]

        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.


        Comment

        • thesagerat@yahoo.co.jp

          #5
          Re: An exotic pointer...

          > I found something weird happening with a pointer:

          Well...not so wierd really.
          [color=blue]
          > 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?[/color]

          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

          Comment

          Working...