public inbox for linux-man@vger.kernel.org
 help / color / mirror / Atom feed
* _Generic.3: EXAMPLES: C++'s static_cast() in C
@ 2022-11-11 14:53 Alejandro Colomar
  2022-11-11 15:11 ` Alejandro Colomar
  0 siblings, 1 reply; 7+ messages in thread
From: Alejandro Colomar @ 2022-11-11 14:53 UTC (permalink / raw)
  To: linux-man; +Cc: Andrew Clayton


[-- Attachment #1.1: Type: text/plain, Size: 9188 bytes --]

Dear readers,

I've been developing a cast macro for C that is similar to C++'s static_cast(), 
which allows to:

- Cast between a limited set of types (actually, pointers to those types).
- Can add const, but not remove it.
- Easily grep for all casts.

But forbids:

- Cast between unrelated types.
- Removing const.

This improves type safety in C, where casts allow programmers to commit all 
kinds of crimes by disabling most compiler warnings.

The macro I originally wrote, allows to convert between u_char and char, for a 
code base that uses u_char internally but has to interface libc and syscalls. 
That one is unnecessary for most code bases which just use char (and that's how 
it should be for strings; if you want unsigned 'char's, you should use 
'-funsigned-char').

But there are cases where the kernel or libc forces us to use casts, like for 
example in bind(2).  That's for what the following macro is, and I plan to add 
it to the EXAMPLES section in _Generic(3), replacing the previous program.

The macro itself is quite huge, which might discourage some, but it is not so 
complex.  I'll release it to the public domain.  Could you please review it?

Cheers,

Alex

---

#define sockaddr_cast(t, p)                            \
     _Generic(&*(p),                                    \
     struct sockaddr *:                                 \
         _Generic((t) NULL,                             \
         struct sockaddr_in *: (t) (p),                 \
         const struct sickaddr_in *: (t) (p),           \
         struct sockaddr_in6 *: (t) (p),                \
         const struct sickaddr_in6 *: (t) (p),          \
         struct sockaddr_un *: (t) (p),                 \
         const struct sickaddr_un *: (t) (p),           \
         struct sockaddr_storage *: (t) (p),            \
         const struct sickaddr_storage *: (t) (p),      \
         default: (p)),                                 \
     struct sockaddr **:                                \
         _Generic((t) NULL,                             \
         struct sockaddr_in **: (t) (p),                \
         struct sockaddr_in6 **: (t) (p),               \
         struct sockaddr_un **: (t) (p),                \
         struct sockaddr_storage **: (t) (p),           \
         default: (p)),                                 \
     const struct sockaddr *:                           \
         _Generic((t) NULL,                             \
         const struct sockaddr_in *: (t) (p),           \
         const struct sockaddr_in6 *: (t) (p),          \
         const struct sockaddr_un *: (t) (p),           \
         const struct sockaddr_storage *: (t) (p),      \
         default: (p)),                                 \
                                                        \
     struct sockaddr_in *:                              \
         _Generic((t) NULL,                             \
         struct sockaddr *: (t) (p),                    \
         const struct sickaddr *: (t) (p),              \
         struct sockaddr_in6 *: (t) (p),                \
         const struct sickaddr_in6 *: (t) (p),          \
         struct sockaddr_un *: (t) (p),                 \
         const struct sickaddr_un *: (t) (p),           \
         struct sockaddr_storage *: (t) (p),            \
         const struct sickaddr_storage *: (t) (p),      \
         default: (p)),                                 \
     struct sockaddr_in **:                             \
         _Generic((t) NULL,                             \
         struct sockaddr **: (t) (p),                   \
         struct sockaddr_in6 **: (t) (p),               \
         struct sockaddr_un **: (t) (p),                \
         struct sockaddr_storage **: (t) (p),           \
         default: (p)),                                 \
     const struct sockaddr_in *:                        \
         _Generic((t) NULL,                             \
         const struct sockaddr *: (t) (p),              \
         const struct sockaddr_in6 *: (t) (p),          \
         const struct sockaddr_un *: (t) (p),           \
         const struct sockaddr_storage *: (t) (p),      \
         default: (p)),                                 \
                                                        \
     struct sockaddr_in6 *:                             \
         _Generic((t) NULL,                             \
         struct sockaddr *: (t) (p),                    \
         const struct sickaddr *: (t) (p),              \
         struct sockaddr_in *: (t) (p),                 \
         const struct sickaddr_in *: (t) (p),           \
         struct sockaddr_un *: (t) (p),                 \
         const struct sickaddr_un *: (t) (p),           \
         struct sockaddr_storage *: (t) (p),            \
         const struct sickaddr_storage *: (t) (p),      \
         default: (p)),                                 \
     struct sockaddr_in6 **:                            \
         _Generic((t) NULL,                             \
         struct sockaddr **: (t) (p),                   \
         struct sockaddr_in **: (t) (p),                \
         struct sockaddr_un **: (t) (p),                \
         struct sockaddr_storage **: (t) (p),           \
         default: (p)),                                 \
     const struct sockaddr_in6 *:                       \
         _Generic((t) NULL,                             \
         const struct sockaddr *: (t) (p),              \
         const struct sockaddr_in *: (t) (p),           \
         const struct sockaddr_un *: (t) (p),           \
         const struct sockaddr_storage *: (t) (p),      \
         default: (p)),                                 \
                                                        \
     struct sockaddr_un *:                              \
         _Generic((t) NULL,                             \
         struct sockaddr *: (t) (p),                    \
         const struct sickaddr *: (t) (p),              \
         struct sockaddr_in *: (t) (p),                 \
         const struct sickaddr_in *: (t) (p),           \
         struct sockaddr_in6 *: (t) (p),                \
         const struct sickaddr_in6 *: (t) (p),          \
         struct sockaddr_storage *: (t) (p),            \
         const struct sickaddr_storage *: (t) (p),      \
         default: (p)),                                 \
     struct sockaddr_un **:                             \
         _Generic((t) NULL,                             \
         struct sockaddr **: (t) (p),                   \
         struct sockaddr_in **: (t) (p),                \
         struct sockaddr_in6 **: (t) (p),               \
         struct sockaddr_storage **: (t) (p),           \
         default: (p)),                                 \
     const struct sockaddr_un *:                        \
         _Generic((t) NULL,                             \
         const struct sockaddr *: (t) (p),              \
         const struct sockaddr_in *: (t) (p),           \
         const struct sockaddr_in6 *: (t) (p),          \
         const struct sockaddr_storage *: (t) (p),      \
         default: (p)),                                 \
                                                        \
     struct sockaddr_storage *:                         \
         _Generic((t) NULL,                             \
         struct sockaddr *: (t) (p),                    \
         const struct sickaddr *: (t) (p),              \
         struct sockaddr_in *: (t) (p),                 \
         const struct sickaddr_in *: (t) (p),           \
         struct sockaddr_in6 *: (t) (p),                \
         const struct sickaddr_in6 *: (t) (p),          \
         struct sockaddr_un *: (t) (p),                 \
         const struct sickaddr_un *: (t) (p),           \
         default: (p)),                                 \
     struct sockaddr_storage **:                        \
         _Generic((t) NULL,                             \
         struct sockaddr **: (t) (p),                   \
         struct sockaddr_in **: (t) (p),                \
         struct sockaddr_in6 **: (t) (p),               \
         struct sockaddr_un **: (t) (p),                \
         default: (p)),                                 \
     const struct sockaddr_storage *:                   \
         _Generic((t) NULL,                             \
         const struct sockaddr *: (t) (p),              \
         const struct sockaddr_in *: (t) (p),           \
         const struct sockaddr_in6 *: (t) (p),          \
         const struct sockaddr_un *: (t) (p),           \
         default: (p)),                                 \
                                                        \
     default:                                           \
         (p)                                            \
     )

-- 
<http://www.alejandro-colomar.es/>

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-11-12 14:18 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-11-11 14:53 _Generic.3: EXAMPLES: C++'s static_cast() in C Alejandro Colomar
2022-11-11 15:11 ` Alejandro Colomar
2022-11-11 16:54   ` Alejandro Colomar
2022-11-11 17:08     ` Alejandro Colomar
2022-11-11 21:40       ` Alejandro Colomar
2022-11-11 23:06         ` [PATCH v6] _Generic.3: EXAMPLES: Add sockaddr_cast() macro Alejandro Colomar
2022-11-12 14:15           ` [PATCH v7] " Alejandro Colomar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox