Typecasting struct pointers?

I'm trying to get into socket programming, but I am having trouble understanding some of the ways pointers and structs are used.

For example from "Beej's Guide to Network Programming" he has some example code with the following line.

 
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;


In that line he typecasts p,a addrinfo pointer, to a sockaddr_in struct, both structures are no where near similar to each other and I am at a total loss as to how they are filled out. Why does p have to be typecasted? Why can't he just use an actual sockaddr_in pointer, rather than a addrinfo pointer that has been typecasted?

There are other times when typecasting seems to make no sense, such as when typecasting a sockaddr_storage to either a sockaddr_in or a sockaddr_in6
Operator Precedence.
-> has higher precedence than (cast)

So he's not casting p he's casting (p->ai_addr)
Last edited on
So he is typecasting a sockaddr as a sockaddr_in? How does that work(I mean how does the data inside sockaddr get converted over to a sockaddr_in)?
It doesn't, he is just saying "act like whatever ai_addr is pointing to act like a sockaddr_in"
Maybe I am not phrasing my question correctly. ipv4 gets the memory location of p->ai_addr. ai_addr is a sockaddr. ipv4 is a sockaddr_in, they are both completely different structures.

Somehow(This is where I am confused) a sockaddr structure is being used to populate a sockaddr_in structure.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
};

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


Does it work by just dumping all the data inside sockaddr into sockaddr_in? For example, since a short and unsigned short are essentially the same thing, is the sa_family variable inside sockaddr taken as sin_family when converted to a sockaddr_in? Same thing with the sa_data, is the first(sa_data[0]) character taken as the unsigned short int sin_port? So sa_data[1], sa_data[2], sa_data[3] and sa_data[4] are used as the unsigned long s_addr? Since a long is 4 bytes and characters are one byte each?
It's polymorphism in C. The socket library uses struct sockaddr* as the interface. However, the implementation is IP v4 and that actually uses struct sockaddr_in*. We know we're using IP v4 and so we use struct sockaddr_in*. But you need to cast pass the struct sockaddr* in the interface.

If this were C++ struct sockaddr would be an interface class and struct sockaddr_in would be an concrete class that implements struct sockaddr. But it's not C++, it's C and there's no language support for polymorphism.
Could you explain that to me a bit more thoroughly? I read the page about polymorphism on this website, but I don't see how that has anything to do with what I am asking. I don't know what you mean by interface and concrete classes, would an interface class be the inherited class?

Your post shows the idea behind it, but not how it actually works. I still don't understand how the values inside sockaddr are converted to something readable by sockaddr_in.

EDIT: Just ran some tests now that I have the time, it seems what I thought in my other post is right. It just straight dumps the data inside sockaddr into sockaddr_in or rather, it tries to access the sockaddr data in the memory location by using sockaddr_in types rather than sockaddr. That explains why sin_zero is there I suppose.
Last edited on
They aren't. It works for example like this:

1
2
3
4
5
6
7
//lets say you have a class that looks like this in binary
10101010 10101010
^mem1    ^mem2

//If you cast it to some other type that maybe has 4 4-bit values, you might get this when you access it
10101010 10101010
^m1 ^m2  ^m3 ^m4

Maybe I am not phrasing my question correctly. ipv4 gets the memory location of p->ai_addr. ai_addr is a sockaddr. ipv4 is a sockaddr_in, they are both completely different structures.


No. ai_addr and ipv4 are both POINTERS to structures not actualy structures. After that assignment statement they are both looking at the same 16 bytes of memory they're just looking at it "differently"
Topic archived. No new replies allowed.