Hi,
On Fri, 5 Aug 2011, Ulrich Weigand wrote:
> > However, there are situations like the following where you like to take
> > the decision at runtime:
> >
> > char cast_3 (char in_pgm, void * p)
> > {
> > return in_pgm ? (*((char __pgm *) p)) : (*((char *) p));
> > }
>
> That's really an abuse of "void *" ... if you have an address in the
> Flash space, you should never assign it to a "void *".
>
> Instead, if you just have a address and you don't know ahead of time
> whether it refers to Flash or RAM space, you ought to hold that number
> in an "int" (or "short" or whatever integer type is most appropriate),
> and then convert from that integer type to either a "char *" or a
> "char __pgm *".
That would leave standard C. You aren't allowed to construct pointers out
of random integers. I'd rather choose to abuse "void*" to be able to
point into a yet-unspecified address spaces, which becomes specified once
the void* pointer is converted into a non-void pointer (which it must be
because you can't dereference a void pointer, hence it does no harm to
leave its address space unspecified).
That would point to a third address space, call it "undef" :) It would be
superset of default and pgm, conversions between undef to {default,pgm}
are allowed freely (and value preserving, i.e. trivial). Conversion into
undef could be rejected. If they are allowed too, then also conversions
between default and pgm are possible (via an intermediate step over
undef), at which point the whole excercise seems a bit pointless and one
could just as well allow conversions between default and pgm.
Ciao,
Michael.