[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Type-safe typecasts

From: Marc Nieper-Wißkirchen
Subject: Type-safe typecasts
Date: Tue, 6 Apr 2021 09:18:02 +0200


I have been wondering whether it makes sense to add a small utility trying to make typecasts in C as type-safe as possible.

The problem is that typecasts are sometimes unavoidable.  For an example, let's take a look at the following snippet using Gnulib's xlist module:

struct foo
  int bar;
gl_list_t list = gl_list_create_empty (GL_ARRAY_LIST, NULL, NULL, NULL, false);
struct foo foo = { .bar = 1 };
gl_list_add_last (list, &foo);
gl_list_iterator_t i = gl_list_iterator (list);
struct foo *elt;
while (gl_list_iterator_next (&i, (const void **) &elt, NULL))
gl_list_iterator_free (&i);

Here, the typecast '(const void **)' is needed as 'gl_list_iterator_next' expects an argument of that type and because 'struct foo **elt' is not implicitly convertible to 'const void **' (in fact, even not to 'void **').

The problem with this typecast is that the compiler wouldn't have complained if I had forgotten to write the address operator '&' before 'elt'.

So what I have in mind are macros that do a type conversion from A to B and that signal an error on modern compilers if the input is not of type A. For this, the C11 construct _Generic can be used.

The macros could look like

CAST (<from-type>, <to-type>, <expr>)

CVR_CAST (<type>, expr) /* removes cvr qualifier */

ADDRESS_CAST (<from-type>, <to-type>, expr)

expanding, respectively, into

_Generic ((<expr>), (<from-type>): ((<to-type>) (<expr>)))

_Generic ((<expr>), (<type>): ((<type>) (<expr>)),
                    (const <type>): ((<type> (<expr>)),
                    (const volatile <type>): ((<type>) (<expr>)),

_Generic ((<expr>), (<from-type>): (((<to-type>) *) &(<expr>)))

The names and the exact semantics and number of macros are, of course, debatable.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]