An object may be the type of its last cast -- but it also can't
exactly lose the benefit/cost of being cast to a pointer to an
undefined type. As soon as you undefine the type of a pointer, it
loses the remnant of ever having had the initial type in the first
place.

In K&R C, you couldn't cast to void *, that was first introduced in
C89. You had to cast to char *, and then you could cast to some other
type in order to make your array indexes jump sizeof(type),
essentially (on 8-bit byte machines) referencing
&array[(index)*(sizeof(type))].

On 11/10/06, David Schwartz wrote:
>
> > The equivalent of the offending line would be
> >
> > foo((double *)(void *) &j);
> >
> > since any access through a void pointer CAN change the value.

>
> '(double *)(void *)' does not keep some sort of remnant of the 'void *'. The final cast renders the end-result a 'double *' and negates the 'void *'. You cannot cast 'through' another type to get some remnant of that type. (In old C.)


(double *)(void *) can't keep any sort of remnant of the int, as it
becomes never-was-an-int-at-all via the (void *) cast.

It's also illegal to take the address of a register, which destroys
the entire concept of aliasing in the first place -- core has always
been core, and any operation can be performed on any part of core
(with the proviso that the machine code generated by the C compiler
must assure proper alignment for the processor). Trying to treat any
piece of core as anything other than a union of all possible types
(since it can't be a struct, because structs take up more memory to be
able to do what they do, and that violates the assumptions on which
the string library depends, among others) is completely foolhardy, and
gives rise to a situation which would more properly be in the domain
of 'pedantic'.

> > Thank you for showing me why I should always include
> > -fno-strict-aliasing in my gcc commandlines. It's broken, horribly.

>
> Actually, what's broken is not allowing a large class of useful optimizations for the occasional code that chooses to invoke undefined behavior. That said, I do exactly what you suggest. I've had too much old code break horribly and subtly to find the optimizations worth the risk. So my 'official' position is not the same as my personal position.


'occasional'? I've never examined any substantial program in C that
doesn't invoke that -- even if just to be able to read data from disk
into memory.

> C has unions and 'char *', and more recently 'void *'. However, you cannot invoke them and then discard them and expect some 'remnant'. An object is the type of the last cast.
>
> I'm going to go dig out my standard. Maybe I'm misremembering.
>
> DS


An object is the type of the last cast -- but if it's ever cast to
void *, it must be treated as if it were never any type before that.
This may have changed in C99, but I'd really much rather have the
option of selecting which dialect I'm using, if only because code that
does work will suddenly not work if compiled with a new dialect. (Is
the word 'father' or 'goat'? I can't tell...)

-Kyle H
__________________________________________________ ____________________
OpenSSL Project http://www.openssl.org
Development Mailing List openssl-dev@openssl.org
Automated List Manager majordomo@openssl.org