For example, struct sockaddr only contains 1-byte members. Therefore it does not have special requirements on alignment. struct sockaddr_in contains at least one member of 4 bytes (struct in_addr), therefore it also has a alignment requirement of 4 bytes to avoid splitting the 4 byte member between memory words.
In order to support casting pointers to any of these struct types, implementations pad all of these structs to make them all the same size and therefore having sane alignment requirements.
You will not read anything about these kind of problems in POSIX, since these are limititations implied by the hardware architecture.
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys...
Quote: "The sockaddr_storage structure solves the problem of declaring storage for automatic variables which is both large enough and aligned enough for storing the socket address data structure of any family."
You're never going to define the storage for an object of `struct sockaddr`; that's just the "abstract base" so to speak: pointers are cast to that type when calling the API. The API switches to the right department in the code, which converts the pointer back to the right concrete type again, like "struct sockaddr_in". So all that is needed is the property that the "struct sockaddr " type can store and recover any other "struct sockaddr_whatever " pointer.
You're also never going to be doing completely silly things like converting a "struct sockaddr_in " to "struct sockaddr_ax25 " or whatever.
If sin_zero must be zero, why doesn't the bind function make it so?
Don't add a member to the end of a struct just so that padding has a name, and then make me initialize it.
POSIX defines a type called struct sockaddr_storage which is at least as large as the largest sockaddr_* type. There is no need to pad the various sockaddr-s up to that size; the sockaddr_storage can be used to declare storage large enough to receive any address.