3

I'm trying to learn network programming, and C in the process. I'm confused about the structures sockaddr which is a generic adress and sockaddr_in. My book has this to say:

Thus, we can fill in the fields of a sockaddr_in and then cast (a pointer to) it to a (pointer to a) sockaddr and pass it to the socket functions, which look at the sa_family field to learn the actual type, then cast back to the appropriate type.

But it doesn't seem to me that the two structs should be compatible? One has two fields,

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

The other has plenty

struct in_addr {
    uint32_t s_addr;
};

struct sockaddr_in {
    sa_family_t sin_family;
    in_port_t sin_port;
    struct in_addr sin_addr;
    char sin_zero[8];
};

They both have size 16 in memory. I guess this is why they zero-pad the sockaddr_in structure, to enable casting? I'm still confused - can casting ever be meaningful if you don't immidiately cast back? Is it always just a temporary cast, utilizing the fact that the sa_family_t field resides in the first N bits?

user207421
  • 305,947
  • 44
  • 307
  • 483
Benjamin Lindqvist
  • 4,300
  • 3
  • 18
  • 19
  • For all things network related see [**Beej's Guide to Network Programming**](http://beej.us/guide/bgnet/). It is an excellent reference/tutorial for network programming. It is only about **100%** applicable to your current question. – David C. Rankin Sep 05 '15 at 07:54

1 Answers1

1

You are not requested to cast the struct but a pointer to it.

The relevant info for the underlying call, that is which struct is referenced, can be pulled from the sin_family member, which is available in any case.

So in essence the cast is just around to silence the compiler, as the function called expects a pointer to struct sockaddr but in fact gets passed a pointer to a different type.

alk
  • 69,737
  • 10
  • 105
  • 255
  • "silence the compiler" Isn't this UB? – usr Sep 05 '15 at 09:16
  • @usr: It only invokes undefined behaviour if the resulting pointer isn't correctly aligned. C11 Draft 6.3.2.3/7: "*A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined.*" – alk Sep 05 '15 at 09:23
  • OK, creating the pointer might be allowed but dereferencing it is not as far as I know. – usr Sep 05 '15 at 09:28
  • @usr: If the alignment is correct the pointer resulting from the conversion might very well be de-referenced. If this would not be allowed/possible the whole socket interface would be broken, though. – alk Sep 05 '15 at 09:36