Accessing structure members indirectly

Discussion in 'C Programming' started by Kavya, Oct 27, 2006.

  1. Kavya

    Kavya Guest

    Here is the code

    int main(){
    struct node{
    int a;
    int b;
    int c;
    };
    struct node s={3,5,6};
    struct node *ptr=&s;
    printf("%d",*(int*)ptr);
    }

    Will the last printf always result in correct output? Is it safer to
    access data members of structure this way?
     
    Kavya, Oct 27, 2006
    #1
    1. Advertising

  2. Kavya <> wrote:
    > Here is the code


    > int main(){
    > struct node{
    > int a;
    > int b;
    > int c;
    > };
    > struct node s={3,5,6};
    > struct node *ptr=&s;
    > printf("%d",*(int*)ptr);
    > }


    > Will the last printf always result in correct output? Is it safer to
    > access data members of structure this way?


    You are guaranteed that address of the first element of a structure
    is always at the address of the structure, so you can safely access
    the member 'a' of your structure that way (if it's a good idea is
    a totally different question). For the other members it's not safe,
    e.g.

    printf( "%d", * (int *) ((char *) ptr + sizeof(int)));

    is _not_ guranteed to print out the value you stored in the member
    'b' since the compiler is allowed to insert as many padding bytes
    between the structure members as it likes.

    Regards, Jens
    --
    \ Jens Thoms Toerring ___
    \__________________________ http://toerring.de
     
    Jens Thoms Toerring, Oct 27, 2006
    #2
    1. Advertising

  3. Kavya

    Bart Guest

    Kavya wrote:
    > Here is the code
    >
    > int main(){
    > struct node{
    > int a;
    > int b;
    > int c;
    > };
    > struct node s={3,5,6};
    > struct node *ptr=&s;
    > printf("%d",*(int*)ptr);
    > }
    >
    > Will the last printf always result in correct output? Is it safer to
    > access data members of structure this way?


    Why not just use an array instead of inventing convoluted ways to shoot
    yourself in the foot?

    Regards,
    Bart.
     
    Bart, Oct 27, 2006
    #3
  4. Kavya

    Richard Bos Guest

    "Kavya" <> wrote:

    > Here is the code
    >
    > int main(){
    > struct node{
    > int a;
    > int b;
    > int c;
    > };
    > struct node s={3,5,6};
    > struct node *ptr=&s;
    > printf("%d",*(int*)ptr);
    > }
    >
    > Will the last printf always result in correct output?


    Yes, for the first member. The first member of a struct must always have
    the same address as the struct itself. This is required by the Standard.
    For any other member, you don't know that. There could be padding
    between a and b, so ((int *)&s)+1 might not point at s.b.

    > Is it safer to access data members of structure this way?


    Not at all. Accessing them normally is the best way.

    Richard
     
    Richard Bos, Oct 27, 2006
    #4
  5. In article <>,
    Kavya <> wrote:

    >Here is the code


    >int main(){
    > struct node{
    > int a;
    > int b;
    > int c;
    > };
    >struct node s={3,5,6};
    >struct node *ptr=&s;
    >printf("%d",*(int*)ptr);
    >}


    >Will the last printf always result in correct output?


    You haven't defined what output it is that you feel to be "correct".

    >Is it safer to
    >access data members of structure this way?


    Safer than what??

    What the C standards say is that:

    1) the first named member of the structure will always be at offset 0
    from the beginning of the structure

    2) each additional member will be placed in increasing address order

    3) there may be internal padding at any point after the first member,
    including at the end of the structure

    4) bitfields generally follow the increasing address rule, but the order
    of the bits within the internal storage allocation size that
    the implementation uses for bitfields, is up to the implementation


    5) special meaning for a bitfield width of 0


    The first rule ensures that in your example *(int *)&s corresponds
    to s.a. However, *(1 + (int *)&s) will *not* necessarily be s.b
    because of rule 3.

    --
    There are some ideas so wrong that only a very intelligent person
    could believe in them. -- George Orwell
     
    Walter Roberson, Oct 27, 2006
    #5
  6. Kavya

    Kavya Guest

    Thanks alot everyone.
     
    Kavya, Oct 27, 2006
    #6
  7. Kavya <> wrote:

    > int main(){
    > struct node{
    > int a;
    > int b;
    > int c;
    > };
    > struct node s={3,5,6};
    > struct node *ptr=&s;
    > printf("%d",*(int*)ptr);
    > }


    > Will the last printf always result in correct output?


    No, but only because it is implementation-defined whether a newline
    is required after the last line of output:

    printf("%d\n",*(int*)ptr);

    P.S. Main returns int, but you didn't return one. Do so and make your
    execution environment happy.

    --
    C. Benson Manica | I *should* know what I'm talking about - if I
    cbmanica(at)gmail.com | don't, I need to know. Flames welcome.
     
    Christopher Benson-Manica, Oct 27, 2006
    #7
  8. Kavya

    Kavya Guest

    Christopher Benson-Manica wrote:
    > Kavya <> wrote:
    >
    > > int main(){
    > > struct node{
    > > int a;
    > > int b;
    > > int c;
    > > };
    > > struct node s={3,5,6};
    > > struct node *ptr=&s;
    > > printf("%d",*(int*)ptr);
    > > }

    >
    > > Will the last printf always result in correct output?

    >
    > No, but only because it is implementation-defined whether a newline
    > is required after the last line of output:


    Sorry. I didn't get that.

    > P.S. Main returns int, but you didn't return one. Do so and make your
    > execution environment happy.


    Isn't that implicit?
     
    Kavya, Oct 27, 2006
    #8
  9. Kavya <> wrote:

    > > No, but only because it is implementation-defined whether a newline
    > > is required after the last line of output:


    > Sorry. I didn't get that.


    The English version of that sentence is "Things might not work like
    you expect if you don't end your output with a newline."

    > > P.S. Main returns int, but you didn't return one. Do so and make your
    > > execution environment happy.


    > Isn't that implicit?


    Only in C99; you are probably not using a C99 compiler. (In English:
    There are two different standards that govern the C language - C89 and
    C99; many or most C compilers conform to C89 rather than C99. In C89,
    if you fail to return a value from main, your shell or whatever you're
    executing your program in gets a random return value.)

    --
    C. Benson Manica | I *should* know what I'm talking about - if I
    cbmanica(at)gmail.com | don't, I need to know. Flames welcome.
     
    Christopher Benson-Manica, Oct 27, 2006
    #9
  10. Kavya

    Kavya Guest

    Christopher Benson-Manica wrote:
    > Kavya <> wrote:
    >
    > > > No, but only because it is implementation-defined whether a newline
    > > > is required after the last line of output:

    >
    > > Sorry. I didn't get that.

    >
    > The English version of that sentence is "Things might not work like
    > you expect if you don't end your output with a newline."
    >
    > > > P.S. Main returns int, but you didn't return one. Do so and make your
    > > > execution environment happy.

    >
    > > Isn't that implicit?

    >
    > Only in C99; you are probably not using a C99 compiler. (In English:
    > There are two different standards that govern the C language - C89 and
    > C99; many or most C compilers conform to C89 rather than C99. In C89,
    > if you fail to return a value from main, your shell or whatever you're
    > executing your program in gets a random return value.)


    Thanks for the these pointers.
     
    Kavya, Oct 27, 2006
    #10
  11. Kavya wrote:

    > Here is the code
    >
    > int main(){
    > struct node{
    > int a;
    > int b;
    > int c;
    > };
    > struct node s={3,5,6};
    > struct node *ptr=&s;
    > printf("%d",*(int*)ptr);
    > }
    >
    > Will the last printf always result in correct output? Is it safer to
    > access data members of structure this way?


    is offsetof() any use to you? I'm not sure what you are trying to do.


    --
    Nick Keighley

    And so when you think of the future,
    imagine a Pentium stamping on a man's face,
    forever.
     
    Nick Keighley, Oct 27, 2006
    #11
  12. On Fri, 2006-10-27 at 02:56 -0700, Kavya wrote:
    > Here is the code
    >
    > int main(){
    > struct node{
    > int a;
    > int b;
    > int c;
    > };
    > struct node s={3,5,6};
    > struct node *ptr=&s;
    > printf("%d",*(int*)ptr);
    > }
    >
    > Will the last printf always result in correct output? Is it safer to
    > access data members of structure this way?
    >


    I'm pretty sure that "(int) *ptr" will be equally valid and predictable.
    Unfortunately, neither /is/ predictable, so it depends on what you mean
    by "correct" output.

    I believe there is no undefined behaviour, which may be a good
    definition of "correct". (Of course, I could be wrong.)

    --
    Andrew Poelstra <http://www.wpsoftware.net/projects/>
     
    Andrew Poelstra, Oct 27, 2006
    #12
  13. On Fri, 2006-10-27 at 15:18 +0000, Andrew Poelstra wrote:
    > On Fri, 2006-10-27 at 02:56 -0700, Kavya wrote:
    > > Here is the code
    > >
    > > int main(){
    > > struct node{
    > > int a;
    > > int b;
    > > int c;
    > > };
    > > struct node s={3,5,6};
    > > struct node *ptr=&s;
    > > printf("%d",*(int*)ptr);
    > > }
    > >
    > > Will the last printf always result in correct output? Is it safer to
    > > access data members of structure this way?
    > >

    <snip my own incorrectness>
    >


    I missed your struct definition above. Yes, this is in fact correct and
    predictable, but only for the first element. (As has been noted by
    others.)

    --
    Andrew Poelstra <http://www.wpsoftware.net/projects/>
     
    Andrew Poelstra, Oct 27, 2006
    #13
  14. Andrew Poelstra <> writes:
    > On Fri, 2006-10-27 at 02:56 -0700, Kavya wrote:
    >> Here is the code
    >>
    >> int main(){
    >> struct node{
    >> int a;
    >> int b;
    >> int c;
    >> };
    >> struct node s={3,5,6};
    >> struct node *ptr=&s;
    >> printf("%d",*(int*)ptr);
    >> }
    >>
    >> Will the last printf always result in correct output? Is it safer to
    >> access data members of structure this way?

    >
    > I'm pretty sure that "(int) *ptr" will be equally valid and predictable.
    > Unfortunately, neither /is/ predictable, so it depends on what you mean
    > by "correct" output.


    *ptr is of type struct node; you can't convert a struct value to int.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Oct 27, 2006
    #14
  15. Kavya

    Ark Guest

    Jens Thoms Toerring wrote:
    > Kavya <> wrote:
    >> Here is the code

    >
    >> int main(){
    >> struct node{
    >> int a;
    >> int b;
    >> int c;
    >> };
    >> struct node s={3,5,6};
    >> struct node *ptr=&s;
    >> printf("%d",*(int*)ptr);
    >> }

    >
    >> Will the last printf always result in correct output? Is it safer to
    >> access data members of structure this way?

    >
    > You are guaranteed that address of the first element of a structure
    > is always at the address of the structure, so you can safely access
    > the member 'a' of your structure that way (if it's a good idea is
    > a totally different question). For the other members it's not safe,
    > e.g.
    >
    > printf( "%d", * (int *) ((char *) ptr + sizeof(int)));
    >
    > is _not_ guranteed to print out the value you stored in the member
    > 'b' since the compiler is allowed to insert as many padding bytes
    > between the structure members as it likes.


    However, b can be portably printed using
    printf("%d", *(int*)((char*)ptr + offsetof(struct node, b)));

    As to the wisdom of this technique... Occasionally, one may need/want to
    parse data consisting of "derived types" like
    struct type1 {
    int RTTI;
    struct base_t base;
    struct type1_specific more;
    };
    struct type3 {
    int RTTI;
    struct base_t base;
    struct type3_specific more;
    };
    Here, an offsetof-based technique may be useful.

    - Ark
     
    Ark, Oct 28, 2006
    #15
    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. Wells
    Replies:
    5
    Views:
    3,281
    Thomas Weidenfeller
    May 17, 2004
  2. python newbie
    Replies:
    4
    Views:
    345
    python newbie
    Nov 30, 2003
  3. swisscheese

    Passing a method indirectly

    swisscheese, Mar 4, 2006, in forum: Python
    Replies:
    4
    Views:
    266
    swisscheese
    Mar 5, 2006
  4. Replies:
    2
    Views:
    1,061
    Marek Vondrak
    Feb 11, 2006
  5. Stefan Rosi

    Accessing WebService indirectly

    Stefan Rosi, Dec 10, 2004, in forum: ASP .Net Web Services
    Replies:
    1
    Views:
    204
    Dan Rogers
    Dec 13, 2004
Loading...

Share This Page