Reputation: 18552
I already knew pointer of a struct can be cast to another pointer of a struct with equivalent memory layout.
However, in the following piece of code:
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MYPORT "3490" // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
int main(void)
{
struct sockaddr_storage their_addr;
socklen_t addr_size;
struct addrinfo hints, *res;
int sockfd, new_fd;
// !! don't forget your error checking for these calls !!
// first, load up address structs with getaddrinfo():
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // use IPv4 or IPv6, whichever
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
getaddrinfo(NULL, MYPORT, &hints, &res);
// make a socket, bind it, and listen on it:
sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
bind(sockfd, res->ai_addr, res->ai_addrlen);
listen(sockfd, BACKLOG);
// now accept an incoming connection:
addr_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size);
// ready to communicate on socket descriptor new_fd!
.
.
.
struct sockaddr_storage their_addr
is cast to (struct sockaddr *)&their_addr
. The layout of each struct is:
struct sockaddr {
unsigned short sa_family; // address family, AF_xxx
char sa_data[14]; // 14 bytes of protocol address
};
and:
struct sockaddr_storage {
sa_family_t ss_family; // address family
// all this is padding, implementation specific, ignore it:
char __ss_pad1[_SS_PAD1SIZE];
int64_t __ss_align;
char __ss_pad2[_SS_PAD2SIZE];
};
socktaddr_storage is definitely a bigger information storage, so it can be cast to whatever smaller than it to fit a function declaration. Inside the function, it does not matter what type of struct is, as long as the passed struct into the function has enough memory blocks for the function to operate as the required struct. Is this correct?
Upvotes: 2
Views: 1251
Reputation: 20272
Yes, it is correct. Basically, its similar to converting a derived class pointer to a base class pointer (and that's how it is implemented in C, in fact).
The content of the 14 bytes will be set based on the value of the ss_family
, and then you can convert it to one of the specific structs.
Upvotes: 3