problem with a casted pointer

Discussion in 'C Programming' started by Raj Pashwar, Oct 8, 2011.

  1. Raj Pashwar

    Raj Pashwar Guest

    ------------------------------- Here is my
    program------------------------------------------

    #include <stdioi.h>
    #include <stddef.h>

    typedef struct dummy{
    int x,y,z;
    }point;

    main() {
    point a = {1,2,3};
    int *p = (int *)(&a + offsetof(point, y);
    int *q = (int *)(&a + offsetof(point, z);
    printf("%d %d",*p,*q);
    }

    ----------------------------------------------------------
    ---------------------------------------

    my question is will *p and *q really point to (a.x) and (a.y) ?
    i ran this program on DevC++ 4.9.9.2 and i'm getting some garbage
    values as output!
     
    Raj Pashwar, Oct 8, 2011
    #1
    1. Advertising

  2. Raj Pashwar

    James Kuyper Guest

    On 10/08/2011 04:44 PM, Raj Pashwar wrote:
    >
    > ------------------------------- Here is my
    > program------------------------------------------
    >
    > #include <stdioi.h>
    > #include <stddef.h>
    >
    > typedef struct dummy{
    > int x,y,z;
    > }point;
    >
    > main() {
    > point a = {1,2,3};
    > int *p = (int *)(&a + offsetof(point, y);
    > int *q = (int *)(&a + offsetof(point, z);
    > printf("%d %d",*p,*q);
    > }
    >
    > ----------------------------------------------------------
    > ---------------------------------------
    >
    > my question is will *p and *q really point to (a.x) and (a.y) ?


    The behavior of your program is undefined. To explain why, it's easier
    if I introduce two new objects:

    point array[8];
    point *pp = array;

    Also, I will assume, in order to make my explanation more concrete, that
    we're using an implementation where sizeof(int)==2, and puts no padding
    in struct dummy. Then sizeof(point) == 6, offsetof(point,y)==2, and
    offsetof(point, z)==4.

    When you add an integer N to a pointer, it shifts that pointer by a
    large enough amount memory to store N copies of the thing it points at.
    Therfore, while pp currently points at array[0], pp+offsetof(point,y)
    points at p[2]. pp+offsetof(point,z) points at array[4]. If converted to
    (int*), those pointers would point at the 'x' members of those structures.

    For the purposes of this rule, a single object is treated as an array of
    length 1. Therefore, &a+offsetof(point,y) would, in principle, point at
    a memory location that hasn't necessarily been reserved for use by your
    program. That's why the behavior of your program is undefined.

    To get the results you desire, you need to use:

    int *p = (int*)((char*)&a + offsetof(point, y));

    Since the sizeof(char)==1, adding N to a char* pointer moves it forward
    by N bytes, which is what you are trying to do.

    > i ran this program on DevC++ 4.9.9.2 and i'm getting some garbage
    > values as output!


    That's one of the plausible results from attempting to read memory that
    you're not supposed to be reading.
    --
    James Kuyper
     
    James Kuyper, Oct 8, 2011
    #2
    1. Advertising

  3. Raj Pashwar <> writes:

    > ------------------------------- Here is my
    > program------------------------------------------
    >
    > #include <stdioi.h>
    > #include <stddef.h>
    >
    > typedef struct dummy{
    > int x,y,z;
    > }point;
    >
    > main() {
    > point a = {1,2,3};
    > int *p = (int *)(&a + offsetof(point, y);
    > int *q = (int *)(&a + offsetof(point, z);
    > printf("%d %d",*p,*q);
    > }
    >
    > ----------------------------------------------------------
    > ---------------------------------------
    >
    > my question is will *p and *q really point to (a.x) and (a.y) ?
    > i ran this program on DevC++ 4.9.9.2 and i'm getting some garbage
    > values as output!


    Your question has been answered, but you might be missing a key piece of
    information. You can write:

    int *p = &a.y;

    Now, you may know this, but if you do, I am puzzled by why you've be
    trying get this same effect with offsetof. Anyway, it seemed worth
    checking that you know the direct route.

    Since I am posting... In most English dialects, the past participle of
    the verb "to cast" is "cast". "The die was cast." "The pointer was cast
    to another type."

    --
    Ben.
     
    Ben Bacarisse, Oct 8, 2011
    #3
  4. Raj Pashwar <> writes:
    > ------------------------------- Here is my
    > program------------------------------------------
    >
    > #include <stdioi.h>


    Typo: <stdio.h>, not <stdioi.h>. It's always best to copy-and-paste
    your code.

    > #include <stddef.h>
    >
    > typedef struct dummy{
    > int x,y,z;
    > }point;
    >
    > main() {


    Should be "int main(void)".

    > point a = {1,2,3};
    > int *p = (int *)(&a + offsetof(point, y);


    &a is the address of a and is of type point*. If sizeof (int) == 4,
    offsetof(point, y) is probably 4. Adding 4 to a point* advances the
    pointer by 4 point objects, *not* by 4 bytes.

    > int *q = (int *)(&a + offsetof(point, z);


    Likewise.

    > printf("%d %d",*p,*q);


    You should print a newline ("\n") at the end of the line of output.

    > }
    >
    > ----------------------------------------------------------
    > ---------------------------------------
    >
    > my question is will *p and *q really point to (a.x) and (a.y) ?
    > i ran this program on DevC++ 4.9.9.2 and i'm getting some garbage
    > values as output!


    Your program's behavior is undefined.

    Simpler:

    int *p = &a.y;
    int *q = &a.z;

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Oct 8, 2011
    #4
  5. On Sat, 08 Oct 2011 16:44:26 -0400, Raj Pashwar
    <> wrote:

    >
    > ------------------------------- Here is my
    > program------------------------------------------
    >
    > #include <stdioi.h>
    > #include <stddef.h>
    >
    > typedef struct dummy{
    > int x,y,z;
    > }point;
    >
    > main() {
    > point a = {1,2,3};
    > int *p = (int *)(&a + offsetof(point, y);
    > int *q = (int *)(&a + offsetof(point, z);
    > printf("%d %d",*p,*q);
    > }


    The problem is not with the pointers which have been cast, it's with
    the pointers which have NOT been cast.
    Because &a has type "pointer to structure", adding an offset to it
    does not produce a pointer inside that structure. If you want to do
    this using offsetof, you should cast &a to type (unsigned char *), i.e.

    int *p = (int *)((char *)&a + offsetof(point, y));
    int *q = (int *)((char *)&a + offsetof(point, z));

    Although, as others have said, it would be better in this small example
    to write it simply as
    int *p = &(a.y);
    int *q = &(a.z);

    (Note also that you don't need the "dummy" struct tag. The only reason
    to name your structs this way is if you're actually going to be using
    that tag, and if you're defining the structure type with a typedef, the
    only reason I can think of for doing that would be if the structure
    contains a pointer to its own type).

    --
    Morris Keesan --
     
    Morris Keesan, Oct 10, 2011
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Pat
    Replies:
    1
    Views:
    276
    Victor Bazarov
    Feb 22, 2007
  2. praveen

    problem with a casted pointer

    praveen, Jun 29, 2007, in forum: C Programming
    Replies:
    15
    Views:
    489
    David Thompson
    Jul 22, 2007
  3. kkirtac

    Problem on using a casted void pointer

    kkirtac, Sep 23, 2007, in forum: C Programming
    Replies:
    10
    Views:
    658
    kkirtac
    Sep 24, 2007
  4. Ravi
    Replies:
    11
    Views:
    1,435
  5. Replies:
    2
    Views:
    98
    Barry Schwarz
    Feb 14, 2014
Loading...

Share This Page