Re: About casts (and pointers)



On Mon, 18 Apr 2005 15:05:14 -0700, sunglo wrote:

> Some time a go, in a discussion here in comp.lang.c, I learnt that it's
> better not to use a (sometype **) where a (void **) is expected (using
> a cast). Part of the discussion boiled down to the rule: if I cast a
> (sometype **) to a (void **) I am making a number of assumptions about
> the implementation's (void **) representation and length.

That's not the real problem (or at least only half of the problem).
Casting something ** to void ** gives the compiler the chance to change
the representation of the result to something appropriate for a void **
value. There's no guarantee that void ** can represent the result, so
there is a possibilty of failure, but this can work even if something **
and void ** have different representations.

The bigger problem is what you do with the void ** value once you have it.
You probably want to dereference it to get a void * value (trying to use
void ** as some sort of "generic" pointer to pointer). This is where
things get very nasty. Your sometype ** pointer is presumably pointing at
a sometype * pointer. If you dereference the void ** value you are trying
to reinterpret the something * pointer as if it is a void * pointer. This
would be a direct reinterpretation of the object representation which
would fail if the representations are different.

> Specifically,
> if I do the above cast I'm assuming that a (sometype **) and a (void
> **) have the same size and representation, and this might not always be
> true. Ok, all clear up to this point.

They don't have to, but something * and void * probably do.

> But now my question is: does the above rule generalize to *every*
> possible cast (expecially those where pointers are involved)? Is every
> explicit cast unsafe? (Here I'm not talking about conversions to/from
> void *, which I know are safe if performed implicitly by the language.
> I also know that casts are better avoided unless strictly needed. But
> I'm curious to know how things work).

Conversion to and from pointers to character types is as safe as void *.

> As an example, look at the widely used cast (struct sockaddr_in *) to
> (struct sockaddr *). Is that safe?

As others have pointed out it would be difficult for an implementation to
make conversion between pointers to structure types fail. But that's not
really the correct way of looking at this. If we assume that the types you
mention are part of an implementation provided library that adheres to a
specification that requires such conversions to work (i.e. as an extension
to C) then those implementations will have to make sure that it works
irrespective of what C itself guarantees.

So, yes, this is safe. But not because C says that it is safe.

>From the Unix world you just have to look at dlsym() for something far
more evil (mixing function and object pointers), but the same
considerations apply.

> Seems to me that, as in the case of (void **), that cast assumes that
> the size and representation of a (struct sockaddr *) are the same of a
> (struct sockaddr_in *). Should this be done using an intermediate (void
> *)?

Again, when you convert between two types those types don't have to have
the same representation, the conversion can make any necessary
adjustments, except that this doesn't guarantee that the value is
representable in the target type.

Lawrence




.



Relevant Pages

  • Re: Can I Trust Pointer Arithmetic In Re-Allocated Memory?
    ... You can't do pointer arithmetic on a void* value. ... qsort behaves in a manner consistent with its specification. ... actually works as advertised...but doesn't mean that the cast is ...
    (comp.lang.c)
  • Re: Common misconceptions about C (C95)
    ... Cast it to suitable type instead. ... The void and void * types come from C++ which has a better rules for them. ... object as an array of bytes (unsigned char *). ... it's okay for that pointer to be a pointer to unsigned char *. ...
    (comp.lang.c)
  • Re: dynamic_cast does not work as specified
    ... then p is a pointer to an object of type SubThing. ... SubThing* via a C-style cast. ... virtual void ShowPURE; ... type-id must be a derived class of expression [note that the simple explanation could be ...
    (microsoft.public.vc.mfc)
  • Re: [RFC] timers, pointers to functions and type safety
    ... * they have callback of type void ... callback is called by the code that even in theory has no ... cast to unsigned long and cast back in the callback. ... number - not a pointer cast to unsigned long, not an index in array, etc. ...
    (Linux-Kernel)
  • Re: interchangeability of types
    ... 26 A pointer to void shall have the same representation and alignment ...
    (comp.std.c)