Type Casting IPv4 and IPv6 structures to Generic Structures

Discussion in 'C Programming' started by tweak, Jun 10, 2004.

  1. tweak

    tweak Guest

    I'm struggling with the concept of typecasting when
    setting up a TCP client.

    Here's a code snip (modified from W. Richard Stevens Unix Programming
    book) to demonstrate where I am struggling:

    int sockfd;
    struct sockaddr_in servaddr;

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(13); /* PORT 13 */

    /* argv[1] = "127.0.0.1" */

    if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr)) <= 0 ) {
    perror("inet_pton()");
    exit(1);
    }

    if ( (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) <
    0) {
    perror("connect()");
    exit(1);
    }

    When this line occurs:

    (struct sockaddr *) &servaddr

    the previously assigned values within servaddr are typecast to struct
    sockaddr,
    which is defined as:

    struct sockaddr {
    uint8_t sa_len;
    sa_family_t sa_family;
    char sa_data[14];
    };

    My confusion is how sa_data[14] becomes populated. I do not
    understand the conversion.

    Can anyone help me out?

    I stepped through the code creating a pointer of type struct sockaddr
    and pointed it to the address of servaddr. But I do not understand
    why sa_data[14] would have data looking like \111\0\r\0\0 . . .
    nor do I understand how to convert that string back to it's original
    form.

    Any help would be appreciated.

    Thanks,

    Brian

    P.S. I'm compiling using gcc, and debuggin with gdb.
    tweak, Jun 10, 2004
    #1
    1. Advertising

  2. tweak

    Grumble Guest

    tweak wrote:

    > I'm struggling with the concept of typecasting when setting
    > up a TCP client.
    >
    > Here's a code snip (modified from W. Richard Stevens Unix
    > Programming book) to demonstrate where I am struggling:


    Try comp.unix.programmer or (perhaps) comp.os.linux.development.apps
    Grumble, Jun 10, 2004
    #2
    1. Advertising

  3. tweak

    tweak Guest

    I do not see why typecasting structures would be specific to unix.
    You should be able to do this across platforms. I am posting here
    to find out about the conversion between the two structures. I
    do not understand the integer to char[] type conversion happening
    when I write:

    (struct sockaddr *) &servaddr

    I can setup a pointer of type struct sockaddr and see in gdb
    the conversion. I just don't understand it.

    Here's some code to do that;

    struct sockaddr *test;

    test = (struct sockaddr *) &servaddr

    the above just passes the address to the pointer test.

    Now in gdb, I can do a display of *test and see what's
    in the structure. But I do not understand the char[]
    conversion.

    Thanks,

    Brian

    P.S. I posted this thread again under a different name, hoping
    to get general C answers about the conversion without scaring
    away folks that haven't messed with socket programming.


    Grumble wrote:
    > tweak wrote:
    >
    >> I'm struggling with the concept of typecasting when setting
    >> up a TCP client.
    >>
    >> Here's a code snip (modified from W. Richard Stevens Unix
    >> Programming book) to demonstrate where I am struggling:

    >
    >
    > Try comp.unix.programmer or (perhaps) comp.os.linux.development.apps
    >
    tweak, Jun 10, 2004
    #3
  4. "tweak" <> wrote in message
    news:us_xc.30344$My6.19961@fed1read05...
    > I do not see why typecasting structures would be specific to unix.
    > You should be able to do this across platforms. I am posting here
    > to find out about the conversion between the two structures. I
    > do not understand the integer to char[] type conversion happening
    > when I write:


    To avoid offending some here, you should simplify your question to the
    minimal code needed, including all the type definitions that are not part of
    Standard C, like this:

    struct foo {
    int a,b,c,d;
    int e;
    }

    struct bar {
    int a,b,c,d;
    char e[sizeof(int)];
    }

    Now, if I understand correctly, your question is what happens when you cast
    a (struct foo *) to a (struct bar *).

    The short answer is: absolutely nothing at the time of the cast, but
    accessing the 'e' member (of the casted form) invokes implementation-defined
    behavior. (I think)

    > Now in gdb, I can do a display of *test and see what's
    > in the structure. But I do not understand the char[]
    > conversion.


    There is no conversion. In the particular case you cite, there are many
    variants of struct sockaddr each with unique contents; the char[] at the end
    is padding such that all of the structs have the same size. This allows one
    to pass a (struct sockaddr_in *) to a function expecting a (struct sockaddr
    *), provided you also pass an idenfier, i.e. AF_INET, which tells the
    receiving function how to properly cast the argument back to extract its
    contents.

    S

    --
    Stephen Sprunk "Stupid people surround themselves with smart
    CCIE #3723 people. Smart people surround themselves with
    K5SSS smart people who disagree with them." --Aaron Sorkin
    Stephen Sprunk, Jun 10, 2004
    #4
  5. tweak

    Alan Balmer Guest

    On Wed, 09 Jun 2004 23:18:43 -0700, tweak <> wrote:

    >(struct sockaddr *) &servaddr
    >
    >the previously assigned values within servaddr are typecast to struct
    >sockaddr,
    >which is defined as:
    >
    >struct sockaddr {
    > uint8_t sa_len;
    > sa_family_t sa_family;
    > char sa_data[14];
    >};
    >
    >My confusion is how sa_data[14] becomes populated. I do not
    >understand the conversion.


    It's not really a conversion. Nothing is moved or changed. You are
    just pretending that block of storage is now a struct sockaddr, where
    before you were pretending it was a struct sockaddr_in. Whatever was
    in those storage locations is still there.

    --
    Al Balmer
    Balmer Consulting
    Alan Balmer, Jun 10, 2004
    #5
  6. tweak

    Dan Pop Guest

    In <> "Stephen Sprunk" <> writes:

    >"tweak" <> wrote in message
    >news:us_xc.30344$My6.19961@fed1read05...
    >> I do not see why typecasting structures would be specific to unix.
    >> You should be able to do this across platforms. I am posting here
    >> to find out about the conversion between the two structures. I
    >> do not understand the integer to char[] type conversion happening
    >> when I write:

    >
    >To avoid offending some here, you should simplify your question to the
    >minimal code needed, including all the type definitions that are not part of
    >Standard C, like this:
    >
    >struct foo {
    > int a,b,c,d;
    > int e;
    >}
    >
    >struct bar {
    > int a,b,c,d;
    > char e[sizeof(int)];
    >}
    >
    >Now, if I understand correctly, your question is what happens when you cast
    >a (struct foo *) to a (struct bar *).
    >
    >The short answer is: absolutely nothing at the time of the cast, but


    This is not neccesarily correct. Casts between different types mean
    conversions and there is nothing in the C standard telling us that
    pointers to different structures use the same representation.
    What is true is that the pointed-to object is not affected in any
    way by the cast.

    >accessing the 'e' member (of the casted form) invokes implementation-defined
    >behavior. (I think)


    It depends on how you access it. Barring a pathological implementation
    that inserts arbitrary padding, if you treat the array e as containing
    an int, everything is fine. If you look at it on a byte by byte basis,
    then it's better to declare it as array of unsigned char. In that case,
    you can access the representation of the corresponding field of struct
    foo.

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
    Dan Pop, Jun 10, 2004
    #6
  7. tweak

    Dan Pop Guest

    In <> Alan Balmer <> writes:

    >On Wed, 09 Jun 2004 23:18:43 -0700, tweak <> wrote:
    >
    >>(struct sockaddr *) &servaddr
    >>
    >>the previously assigned values within servaddr are typecast to struct
    >>sockaddr,
    >>which is defined as:
    >>
    >>struct sockaddr {
    >> uint8_t sa_len;
    >> sa_family_t sa_family;
    >> char sa_data[14];
    >>};
    >>
    >>My confusion is how sa_data[14] becomes populated. I do not
    >>understand the conversion.

    >
    >It's not really a conversion. Nothing is moved or changed.


    Except for the pointer value itself, that is *converted* from one type to
    another. If you claim that this conversion is a no-op, please provide
    chapter and verse.

    Dan
    --
    Dan Pop
    DESY Zeuthen, RZ group
    Email:
    Dan Pop, Jun 10, 2004
    #7
  8. tweak

    Chris Torek Guest

    >On Wed, 09 Jun 2004 23:18:43 -0700, tweak <> wrote:
    >>(struct sockaddr *) &servaddr
    >>... the previously assigned values within servaddr are typecast to
    >>struct sockaddr ...


    In article <news:eek:>
    Alan Balmer <> writes:
    >It's not really a conversion. Nothing is moved or changed.


    Well, more precisely, there *is* a conversion -- but the conversion
    is not the one quoted in ">>" above.

    >You are just pretending that block of storage is now a struct
    >sockaddr, where before you were pretending it was a struct
    >sockaddr_in. Whatever was in those storage locations is still there.


    This, of course, is correct.

    The result of "&servaddr" -- a value of type "pointer to struct A"
    (for some A) -- is converted to a new value of type "pointer to
    struct B" (for some B). The data to which the original pointer
    points are unchanged, but whether the new pointer is at all useful
    is specific to the implementation.

    Unix-like systems with "sockaddr"s and "sockaddr_in"s -- let me
    call these "POSIX systems" for short, although even that is not
    strictly true -- are much more strongly constrained than is "C in
    general", so that while much of POSIX can be written using C, there
    are machines that can run C that can never run POSIX. This is
    similar to the way that all trucks are vehicles, but not all vehicles
    are trucks. If you specify "a vehicle that can carry three tons
    of cargo", you have ruled out a lot of possible vehicles -- but
    now you can be sure that you can do something with the remaining
    subset. (If you load three tons of cargo onto a Yugo or a racecar,
    what happens?) If you specify "a computer that has POSIX", you have
    ruled out a lot of possible computers, but now you can be sure you
    can do something -- sockaddr and sockaddr_in, for instance -- with
    the remaining subset.

    Here in comp.lang.c we try not to get too specific about large-scale
    cargo-hauling, in case your interests are Formula 1 racers or
    restoring Model Ts. :) We try to talk about things that apply
    to *all* C systems, as defined by the C standard.
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
    Chris Torek, Jun 10, 2004
    #8
  9. tweak

    Alan Balmer Guest

    On 10 Jun 2004 16:12:44 GMT, (Dan Pop) wrote:

    >In <> Alan Balmer <> writes:
    >
    >>On Wed, 09 Jun 2004 23:18:43 -0700, tweak <> wrote:
    >>
    >>>(struct sockaddr *) &servaddr
    >>>
    >>>the previously assigned values within servaddr are typecast to struct
    >>>sockaddr,
    >>>which is defined as:
    >>>
    >>>struct sockaddr {
    >>> uint8_t sa_len;
    >>> sa_family_t sa_family;
    >>> char sa_data[14];
    >>>};
    >>>
    >>>My confusion is how sa_data[14] becomes populated. I do not
    >>>understand the conversion.

    >>
    >>It's not really a conversion. Nothing is moved or changed.

    >
    >Except for the pointer value itself, that is *converted* from one type to
    >another. If you claim that this conversion is a no-op, please provide
    >chapter and verse.
    >

    He didn't ask about the pointer value, but the contents of the struct.

    Go away.

    --
    Al Balmer
    Balmer Consulting
    Alan Balmer, Jun 10, 2004
    #9
  10. tweak

    tweak Guest

    Dan Pop wrote:
    > In <> "Stephen Sprunk" <> writes:
    >
    >
    >>"tweak" <> wrote in message
    >>news:us_xc.30344$My6.19961@fed1read05...
    >>
    >>>I do not see why typecasting structures would be specific to unix.
    >>>You should be able to do this across platforms. I am posting here
    >>>to find out about the conversion between the two structures. I
    >>>do not understand the integer to char[] type conversion happening
    >>>when I write:

    >>
    >>To avoid offending some here, you should simplify your question to the
    >>minimal code needed, including all the type definitions that are not part of
    >>Standard C, like this:
    >>
    >>struct foo {
    >> int a,b,c,d;
    >> int e;
    >>}
    >>
    >>struct bar {
    >> int a,b,c,d;
    >> char e[sizeof(int)];
    >>}
    >>
    >>Now, if I understand correctly, your question is what happens when you cast
    >>a (struct foo *) to a (struct bar *).
    >>
    >>The short answer is: absolutely nothing at the time of the cast, but

    >
    >
    > This is not neccesarily correct. Casts between different types mean
    > conversions and there is nothing in the C standard telling us that
    > pointers to different structures use the same representation.
    > What is true is that the pointed-to object is not affected in any
    > way by the cast.
    >
    >
    >>accessing the 'e' member (of the casted form) invokes implementation-defined
    >>behavior. (I think)

    >
    >
    > It depends on how you access it. Barring a pathological implementation
    > that inserts arbitrary padding, if you treat the array e as containing
    > an int, everything is fine. If you look at it on a byte by byte basis,
    > then it's better to declare it as array of unsigned char. In that case,
    > you can access the representation of the corresponding field of struct
    > foo.
    >
    > Dan


    I will now modify my code going forward to simple examples.

    Cheers,

    Brian
    tweak, Jun 11, 2004
    #10
  11. tweak

    tweak Guest

    Alan Balmer wrote:
    > On Wed, 09 Jun 2004 23:18:43 -0700, tweak <> wrote:
    >
    >
    >>(struct sockaddr *) &servaddr
    >>
    >>the previously assigned values within servaddr are typecast to struct
    >>sockaddr,
    >>which is defined as:
    >>
    >>struct sockaddr {
    >> uint8_t sa_len;
    >> sa_family_t sa_family;
    >> char sa_data[14];
    >>};
    >>
    >>My confusion is how sa_data[14] becomes populated. I do not
    >>understand the conversion.

    >
    >
    > It's not really a conversion. Nothing is moved or changed. You are
    > just pretending that block of storage is now a struct sockaddr, where
    > before you were pretending it was a struct sockaddr_in. Whatever was
    > in those storage locations is still there.
    >


    If you assign the cast portion of the function to a pointer of the
    typecast and dereference that pointer, the values appear to change.
    I will say that convert to something, but don't actually change.

    /* create pointer of type cast */

    struct sockaddr *test;

    /* assign servaddr */

    test = (struct sockaddr *) &servaddr

    in gdb, look at *test after the assignment.

    sa_data looks like "\0\117\r\0 . . . "

    I put the actual output in my response to my typecasting
    structures thread.

    I do not understand sa_data[]. I understand that the last
    zeros exist to establish the structure at a specific size,
    but I do not understand the items before the '\0' padding.

    Any ideas?

    Cheers,

    Brian
    tweak, Jun 11, 2004
    #11
  12. On 10 Jun 2004 16:12:44 GMT, (Dan Pop) wrote:

    >In <> Alan Balmer <> writes:
    >
    >>On Wed, 09 Jun 2004 23:18:43 -0700, tweak <> wrote:
    >>
    >>>(struct sockaddr *) &servaddr
    >>>
    >>>the previously assigned values within servaddr are typecast to struct
    >>>sockaddr,
    >>>which is defined as:
    >>>
    >>>struct sockaddr {
    >>> uint8_t sa_len;
    >>> sa_family_t sa_family;
    >>> char sa_data[14];
    >>>};
    >>>
    >>>My confusion is how sa_data[14] becomes populated. I do not
    >>>understand the conversion.

    >>
    >>It's not really a conversion. Nothing is moved or changed.

    >
    >Except for the pointer value itself, that is *converted* from one type to
    >another. If you claim that this conversion is a no-op, please provide
    >chapter and verse.
    >


    The requirement that all pointers to struct have the same
    representation would seem to satisfy your request.


    <<Remove the del for email>>
    Barry Schwarz, Jun 11, 2004
    #12
  13. tweak

    Ralmin Guest

    "Dan Pop" <> wrote:
    > "Stephen Sprunk" <> wrote:
    > > Now, if I understand correctly, your question is what happens
    > > when you cast a (struct foo *) to a (struct bar *).
    > >
    > > The short answer is: absolutely nothing at the time of the
    > > cast, but

    >
    > This is not neccesarily correct. Casts between different types
    > mean conversions and there is nothing in the C standard telling
    > us that pointers to different structures use the same
    > representation. What is true is that the pointed-to object is
    > not affected in any way by the cast.


    C99 6.6.2.1 #26 "All pointers to structure types shall have the same
    representation and alignment requirements as each other."

    The type of the expression changes, but the representation of the pointer
    value does not.

    --
    Simon.
    Ralmin, Jun 11, 2004
    #13
  14. tweak

    CBFalconer Guest

    Barry Schwarz wrote:
    > On 10 Jun 2004 16:12:44 GMT, (Dan Pop) wrote:
    >

    .... snip ...
    >>
    >> Except for the pointer value itself, that is *converted* from
    >> one type to another. If you claim that this conversion is a
    >> no-op, please provide chapter and verse.

    >
    > The requirement that all pointers to struct have the same
    > representation would seem to satisfy your request.


    Meaning they fit in the same space. However they obviously need
    not have the same value, which is some collection of bits. I see
    no prohibition against some variation in some of those bits in
    accordance with the actual type. I also see no reason for any
    implementation to do so.

    --
    Chuck F () ()
    Available for consulting/temporary embedded and systems.
    <http://cbfalconer.home.att.net> USE worldnet address!
    CBFalconer, Jun 11, 2004
    #14
  15. tweak

    Eric Sosman Guest

    Dan Pop wrote:
    > In <> Alan Balmer <> writes:
    >
    >
    >>On Wed, 09 Jun 2004 23:18:43 -0700, tweak <> wrote:
    >>
    >>
    >>>(struct sockaddr *) &servaddr
    >>>
    >>>the previously assigned values within servaddr are typecast to struct
    >>>sockaddr,
    >>>which is defined as:
    >>>
    >>>struct sockaddr {
    >>> uint8_t sa_len;
    >>> sa_family_t sa_family;
    >>> char sa_data[14];
    >>>};
    >>>
    >>>My confusion is how sa_data[14] becomes populated. I do not
    >>>understand the conversion.

    >>
    >>It's not really a conversion. Nothing is moved or changed.

    >
    >
    > Except for the pointer value itself, that is *converted* from one type to
    > another. If you claim that this conversion is a no-op, please provide
    > chapter and verse.


    ISO/IEC 9899:1999, section 6.2.5, paragraph 26, third sentence.

    --
    Eric Sosman, Jun 11, 2004
    #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. Ben
    Replies:
    0
    Views:
    560
  2. heyo
    Replies:
    3
    Views:
    900
    Dan Pop
    Apr 1, 2004
  3. Alfonso Morra
    Replies:
    11
    Views:
    709
    Emmanuel Delahaye
    Sep 24, 2005
  4. Jesse van den Kieboom

    Ipv6 on a ipv4/ipv6 hostname

    Jesse van den Kieboom, Jun 5, 2005, in forum: Ruby
    Replies:
    1
    Views:
    357
    Dibya Prakash
    Jun 5, 2005
  5. snacktime
    Replies:
    3
    Views:
    137
    snacktime
    Oct 30, 2006
Loading...

Share This Page