diff options
| -rw-r--r-- | man3/_Generic.3 | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/man3/_Generic.3 b/man3/_Generic.3 index ddee5f6c4c..6ff5e24ea7 100644 --- a/man3/_Generic.3 +++ b/man3/_Generic.3 @@ -27,12 +27,101 @@ that will behave differently depending on the type of the argument. .SH STANDARDS C11 and later. .SH EXAMPLES +The following code demonstrates how to write +a macro similar to C++'s +.BR \%static_cast (), +which will allow casting safely between a limited set of types. +It is useful for example when calling +system calls or library functions that use compatible structures, +like for example +.BR bind (2) +with +.BR \%sockaddr (3type). +.IP +.EX +/* This code is in the public domain. */ + +#include <netinet/in.h> +#include <sys/socket.h> +#include <sys/un.h> + +#define sockaddr_cast(t, p) \e + _Generic(&*(p), \e + struct sockaddr *: \e + _Generic((typeof_unqual(t)) NULL, \e + struct sockaddr_in *: (t) (p), \e + struct sockaddr_in6 *: (t) (p), \e + struct sockaddr_un *: (t) (p), \e + default: (p)), \e + struct sockaddr **: \e + _Generic((typeof_unqual(t)) NULL, \e + struct sockaddr_in **: (t) (p), \e + struct sockaddr_in6 **: (t) (p), \e + struct sockaddr_un **: (t) (p), \e + default: (p)), \e + const struct sockaddr *: \e + _Generic((t) NULL, \e + const struct sockaddr_in *: (t) (p), \e + const struct sockaddr_in6 *: (t) (p), \e + const struct sockaddr_un *: (t) (p), \e + default: (p)), \e + \e + struct sockaddr_in *: \e + _Generic((typeof_unqual(t)) NULL, \e + struct sockaddr *: (t) (p), \e + default: (p)), \e + struct sockaddr_in **: \e + _Generic((typeof_unqual(t)) NULL, \e + struct sockaddr **: (t) (p), \e + default: (p)), \e + const struct sockaddr_in *: \e + _Generic((t) NULL, \e + const struct sockaddr *: (t) (p), \e + default: (p)), \e + \e + struct sockaddr_in6 *: \e + _Generic((typeof_unqual(t)) NULL, \e + struct sockaddr *: (t) (p), \e + default: (p)), \e + struct sockaddr_in6 **: \e + _Generic((typeof_unqual(t)) NULL, \e + struct sockaddr **: (t) (p), \e + default: (p)), \e + const struct sockaddr_in6 *: \e + _Generic((t) NULL, \e + const struct sockaddr *: (t) (p), \e + default: (p)), \e + \e + struct sockaddr_un *: \e + _Generic((typeof_unqual(t)) NULL, \e + struct sockaddr *: (t) (p), \e + default: (p)), \e + struct sockaddr_un **: \e + _Generic((typeof_unqual(t)) NULL, \e + struct sockaddr **: (t) (p), \e + default: (p)), \e + const struct sockaddr_un *: \e + _Generic((t) NULL, \e + const struct sockaddr *: (t) (p), \e + default: (p)), \e + \e + default: \e + (p) \e + ) + +socklen_t slen; +struct sockaddr_un sun; + +slen = sizeof(ss); +getsockname(sfd, sockaddr_cast(struct sockaddr *, &sun), &slen); +.EE +.PP The following program demonstrates how to write a replacement for the standard .BR imaxabs (3) function, which being a function can't really provide what it promises: seamlessly upgrading to the widest available type. -.PP +.IP .\" SRC BEGIN (_Generic.c) .EX #include <stdint.h> |
