3 ms·
> Can you provide an example of where an implicit pointer conversion creates danger? In your malloc example, there's no real danger because you used sizeof. B
by jlokier 5y ago
> Can you provide an example of where an implicit pointer conversion creates danger?
In your malloc example, there's no real danger because you used sizeof. But when it is written with a type like this:
bar = malloc(sizeof(BarType));
Then there's danger if the type of bar does not match BarType *, perhaps after changes.
Writing it like this:
bar = (BarType *)malloc(sizeof(BarType))
ensures the type mismatch will cause a compile-time error instead of UB.
That's not a strong argument, obviously, as you can use sizeof(*bar) instead. But it is an example of a situation where an implicit pointer conversion creates danger.
(I would also argue that a malloc(sizeof(type)) is more idiomatic and familiar C, so using it with other people will raise fewer eyebrows even if it's not strictly the safer choice.)
So when would it occur without sizeof(*bar) being an option? When there's a type-erased container:
foo = list_get(FooType, foo_list, index);
bar = hash_get(BarType, bar_hash_table, key);
If those are generic containers whose accessors return void *, you will be in trouble with UB here if the type of *foo or *bar don't match FooType and BarType respectively, perhaps after changes.
When you add the cast, again the type mismatch will cause a compile-time error.
In this case, there's no need to write the cast at the call site. Since list_get and hash_get must be macros, it's better to put the cast inside those macros. But the cast should exist, to catch the type mismatch, rather than those returning void * and relying on implicit cast rules.
(If you want to get fancy, there's a way to avoid having to pass the container item-type to those macros as an argument, but I've never seen it used in practice.)