Typecasting of structures...

Posted on 2011-05-01
Last Modified: 2012-05-11
Hi I am delving in to network programming and having difficulty in understanding the typecasting effects:

E.g the function is:

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)

and we are passing the following:

accept(sock, (struct sockaddr *)&client, &len))

for struct sockaddr *add, can't i just pass the
address &client, instead of typecasting it with
 (struct sockaddr *), what does typecasting mean in this case.

Question by:tpat
    LVL 31

    Accepted Solution

    include <netinet/in.h>
    // All pointers to socket address structures are often cast to pointers
    // to this type before use in various functions and system calls:
    struct sockaddr {
        unsigned short    sa_family;    // address family, AF_xxx
        char              sa_data[14];  // 14 bytes of protocol address
    // IPv4 AF_INET sockets:
    struct sockaddr_in {
        short            sin_family;   // e.g. AF_INET, AF_INET6
        unsigned short   sin_port;     // e.g. htons(3490)
        struct in_addr   sin_addr;     // see struct in_addr, below
        char             sin_zero[8];  // zero this if you want to

    Open in new window

    In the accept function, addr is expected to be of the data type, struct sockaddr *

    From are these two LOCS:
    struct sockaddr_in serv_addr, cli_addr;
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);

    Open in new window

    Without the (struct sockaddr *) cast, you should get a compiler warning or error due to mismatch pointer types. There is no functional effect to the generated assembly code when using the type cast - the address of cli_addr is passed to accept. The type cast just serves to get past the compiler step.

    Author Comment

    So you mean that functionally it does not make any difference if i use/do not
    use the typecast, however to get the way out of compiler error/warning,
    we need to use the typecast.

    Appreciate you help! Thanks.

    LVL 31

    Assisted Solution

    Right, what the accept needs is the address of cli_addr to fill up the cli_addr structure. However, it accepts a pointer to a different structure that represents an address family, AF_xxx , not necessarily struct sockaddr_in.
    LVL 31

    Expert Comment

    For example, in the link is this IPv6 structure:
    // IPv6 AF_INET6 sockets:
    struct sockaddr_in6 {
        u_int16_t       sin6_family;   // address family, AF_INET6
        u_int16_t       sin6_port;     // port number, Network Byte Order
        u_int32_t       sin6_flowinfo; // IPv6 flow information
        struct in6_addr sin6_addr;     // IPv6 address
        u_int32_t       sin6_scope_id; // Scope ID

    Open in new window

    "the struct sockaddr_in and struct sockaddr_in6 share the same beginning structure as struct sockaddr, and you can freely cast the pointer of one type to the other without any harm"

    "whenever a function says it takes a struct sockaddr* you can cast your struct sockaddr_in*, struct sockaddr_in6*, or struct sockadd_storage* to that type with ease and safety."
    But just make sure that the socklen_t *addrlen argument in accept is large enough to handle the struct that you are using.

    This accept link ( ) shows how to handle either IPv4 or IPv6, when the modality is unspecified. The above IPv6 structure is larger than the IPv4 struct. But if you follow the pattern in this link, you should have no problem. (I'll take this on faith, for now, since I haven't worked with IPv6.)
    struct sockaddr_storage their_addr;
    socklen_t addr_size;
    addr_size = sizeof their_addr;
    new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size);

    Open in new window

    LVL 8

    Assisted Solution

    The socket calls - socket(), bind(), listen(), accept() and connect() - are common to both internet domain and unix domain.
    But, both these domains have different kind of structures:
    Internet Domain uses:
    struct sockaddr_in
        __SOCKADDR_COMMON (sin_);
        in_port_t sin_port;                 /* Port number.  */
        struct in_addr sin_addr;            /* Internet address.  */

        /* Pad to size of `struct sockaddr'.  */
        unsigned char sin_zero[sizeof (struct sockaddr) -
                               __SOCKADDR_COMMON_SIZE -
                               sizeof (in_port_t) -
                               sizeof (struct in_addr)];

    Unix Domain uses:
    struct sockaddr_un
        __SOCKADDR_COMMON (sun_);
        char sun_path[108];         /* Path name.  */

    Now, how to use two different structs as parameters in both kinds of domains.
    To get it working for both, they created a general structure:
    struct sockaddr {
        unsigned short    sa_family;    // address family, AF_xxx
        char              sa_data[14];  // 14 bytes of protocol address

    And while calling these functions, typecast the correct struct.
    Internally, based on the type of domain we are using, the functions will inturn typecast "struct sockaddr" to correct structure and uses it.

    Author Comment

    If that is so,
    can I use accept(sock, (struct sockaddr_inet *)&client, &len)) instead of
    accept(sock, (struct sockaddr *)&client, &len)).

    LVL 8

    Expert Comment

    > can I use accept(sock, (struct sockaddr_inet *)&client, &len))
    I don't think, there is any structure "struct sockaddr_inet".
    The prototype for accept() is:
    int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
    So, while calling accept, you will have to use the same struct that is used in the prototype to typecast.
    So, you should use:
    accept(sock, (struct sockaddr *)&client, &len))
    LVL 31

    Assisted Solution

    By any chance, are you referring to Windows Winsock API? I found a SOCKADDR_INET union that is defined on Windows Vista and later. (Haven't used it myself.)
    But SOCKADDR_INET is a union rather than a struct.
    Here is the definition of SOCKADDR_INET:
    typedef union _SOCKADDR_INET {
      SOCKADDR_IN    Ipv4;
      SOCKADDR_IN6   Ipv6;
      ADDRESS_FAMILY si_family;

    Open in new window

    In Windows, their accept is:
    SOCKET accept(
      __in     SOCKET s,
      __out    struct sockaddr *addr,
      __inout  int *addrlen

    Open in new window
    So, you still want a struct sockaddr * for the 2nd argument.
    LVL 8

    Expert Comment

    tpat -- to get back to your question about the effect of typecasting pointers in C.

    All pointers in C have the same identical implementation.  All pointers have the same format and same size.   Typecasting a pointer doesn't change its format.

    The C compiler catches common programming errors which occur when you pass pointers to one kind of object to a function which expects a different kind of object.  The typecast allows you to tell the compiler that you know that the object is one type but you are sure that it is compatible with some other type.  In this way, casting a pointer makes it more difficult for the compiler to catch errors.  Any time you find that you need to insert a typecast for a pointer, you loose some error checking so you need to be much more careful to be sure that it is correct.  

    Good APIs don't require casting pointers.  The socket API is old was not implemented consistently, which leads to requiring typecasting pointers.
    LVL 34

    Expert Comment

    by:Duncan Roe
    Agree with the general rule to avoid type casting where practicable, but casting sockaddr_in to sockaddr is a classic programming construct - everybody does it

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    Find Ransomware Secrets With All-Source Analysis

    Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

    This tutorial is posted by Aaron Wojnowski, administrator at  To view more iPhone tutorials, visit This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
    The purpose of this article is to fix the unknown display problem in Linux Mint operating system. After installing the OS if you see Display monitor is not recognized then we can install "MESA" utilities to fix this problem or we can install additio…
    Video by: Grant
    The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.
    Video by: Grant
    The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.

    758 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    13 Experts available now in Live!

    Get 1:1 Help Now