This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Tricky(?) aliasing question.
Sergei Organov writes:
> Andrew Haley <aph@redhat.com> writes:
>
> > Sergei Organov writes:
> > > Andrew Haley <aph@redhat.com> writes:
> > >
> > > > Sergei Organov writes:
> > > > > Ian Lance Taylor <iant@google.com> writes:
> > > > > > Sergei Organov <osv@javad.com> writes:
> > > > > >
> >> > > int float_as_int()
> > > > > {
> > > > > h1.f = 1;
> > > > > H0 h0 = *(H0*)&h1.f; // Should be OK? No, it is not?!
> > > >
> > > > I don't think this is OK. Per C99, you can cast to the element type
> > > > from the struct or vice versa, but you can't cast from one struct type
> > > > to another via the first element.
> > >
> > > There is no word "casting" in the definition of the aliasing rules in
> > > C99. It talks about accessing of object through an lvalue of compatible
> > > type. In this example I access stored value of object "h1.f"
> >
> > No, that's not what the code above does. You're accessing an object
> > of type h1 through an lvalue of type h0. Accessing h1.f would have
> > been perfectly OK, but that's not what the code above does.
> >
> > Look at it again:
> >
> > H0 h0 = *(H0*)&h1.f;
> >
> > The LHS of this assignment is of type h0.
>
> Yes.
>
> > The RHS is an object of effective type h1. The fact that you're going
> > via a pointer cast to its first member is neither here nor there.
>
> So "h1.f" is not an object?
This is too silly for words.
> If it is not, it brings us back to the validity of my boo()
> function from the initial post, for which 2 persons (3 including
> me) thought it's OK:
>
> S s;
> int boo()
> {
> s.i = 20;
> // Accessing 's' of type 'S' through 'int'. Is it aliasing rules
> // violation? Maybe yes, but on the other hand this could be
> // considered as accessing 's.i' of type 'int' through 'int' that
> // should be OK from C99 standard POV?
> *(int*)&s = 10;
> return s.i;
> }
>
> Do you think this one is OK then?
Yes. The standard says it's OK.
You can convert a pointer to a struct to the type of its first member,
and back to a pointer to the original struct and the pointer will
still be valid. What you can't do is use that converted pointer to
access an object of incompatible type.
> Anyway, I can rewrite the float_as_int() so that it will access plain
> float f:
>
> float f;
> int float_as_int()
> {
> h1.f = 1;
> H0 h0 = *(H0*)&f; // Should be OK? No, it is not?!
No. The types have to be compatible. If f were of type h0, this
would be OK. But f is of type float, so it isn't.
> return h0.i;
> }
>
> Does it change anything in your reasoning?
No.
Andrew.