Why is sin_addr inside the structure in_addr?

My doubt is related to the following structure of sockets in UNIX :

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
};

Here the member sin_addr is of type struct in_addr.

But I don't get why someone would like to do that as all struct inaddr has is :

struct in_addr {
    unsigned long s_addr;          // load with inet_pton()
};

All in_addr has is just one member s_addr. Why cannot we have something like this :

struct sockaddr_in {
    short            sin_family;   // e.g. AF_INET, AF_INET6
    unsigned short   sin_port;     // e.g. htons(3490)
    unsigned long    s_addr ; 
    char             sin_zero[8];  // zero this if you want to
};

Solution 1:

struct in_addr is sometimes very different than that, depending on what system you're on. On Windows for example:

typedef struct in_addr {
  union {
    struct {
      u_char s_b1,s_b2,s_b3,s_b4;
    } S_un_b;
    struct {
      u_short s_w1,s_w2;
    } S_un_w;
    u_long S_addr;
  } S_un;
} IN_ADDR, *PIN_ADDR, FAR *LPIN_ADDR;

The only requirement is that it contain a member s_addr.

Solution 2:

Because the in_addr structure may contain more than one member.

http://pubs.opengroup.org/onlinepubs/009604599/basedefs/netinet/in.h.html

Solution 3:

struct in_addr is a more than just an integer is because it might have more than in_addr_t. In many systems, it has a union, and the reason of such implementation is for class A/B/C addresses, which are not used now.

Unix Network Programming Volume 1 explains the historical reason in detail:

The reason the sin_addr member is a structure, and not just an in_addr_t, is historical. Earlier releases (4.2BSD) defined the in_addr structure as a union of various structures, to allow access to each of the 4 bytes and to both of the 16-bit values contained within the 32-bit IPv4 address. This was used with class A, B, and C addresses to fetch the appropriate bytes of the address. But with the advent of subnetting and then the disappearance of the various address classes with classless addressing, the need for the union disappeared. Most systems today have done away with the union and just define in_addr as a structure with a single in_addr_t member.