On 01/06/2010 04:09 AM, Joshua Haberman wrote: > Erik Trulsson <ertr1013 <at> student.uu.se> writes: >> On Sun, Jan 03, 2010 at 05:46:48AM +0000, Joshua Haberman wrote: >>> The aliasing policies that GCC implements seem to be more strict than >>> what is in the C99 standard. I am wondering if this is true or whether >>> I am mistaken (I am not an expert on the standard, so the latter is >>> definitely possible). >>> - >>> The relevant text is: >>> - >>> An object shall have its stored value accessed only by an lvalue >>> expression that has one of the following types: >>> - >>> * a type compatible with the effective type of the object, >>> [...] >>> * an aggregate or union type that includes one of the aforementioned >>> types among its members (including, recursively, a member of a >>> subaggregate or contained union), or >>> - >>> To me this allows the following: >>> - >>> int i; >>> union u { int x; } *pu = (union u*)&i; >>> printf("%d\n", pu->x); >>> - >>> In this example, the object "i", which is of type "int", is having its >>> stored value accessed by an lvalue expression of type "union u", which >>> includes the type "int" among its members. >> - >> Even with your interpretation of the C99 standard that example would be >> allowed only if '*pu' is a valid lvalue of type 'union u'. (Since pu->x >> is equivalent to (*pu).x) >> - >> First of all the conversion (union u*)&i is valid only if the alignment >> of 'i' is suitable for an object of type 'union u'. Lets assume that is the >> case. (Otherwise just making that conversion would result in undefined >> behaviour.) (See 6.3.2.3 clause 7.) > > This is true. You could get around this particular point by saying: > > int *i = malloc(sizeof(*i)); > *i = 5; > union u { int x; } *pu = (union u*)i; > printf("%d\n", pu->x); > > ...since the return from malloc() is guaranteed to be suitably aligned for > any object (7.20.3). But your point is taken. > >> There is however no guarantee that the conversion yields a valid >> "pointer to union u". If not then dereferencing it (with the >> expression '*pu') has undefined behaviour. (See 6.5.3.2 clause 4) > > I think this is a bit of a stretch. It is true that 6.5.3.2 says that > dereferencing invalid values has undefined behavior. But if you are > saying that the standard has to explicitly say that a pointer conversion > will not result in an invalid value (even when suitably aligned), then > the following is also undefined: > > int i; > unsigned int *pui = (unsigned int*)&i; > unsigned int ui = *pui; > > Andrew cited 6.3.2.3p2 as support for why this is defined, but that > paragraph deals with qualifiers (const, volatile, and restrict). > "unsigned" is not a qualifier.
You are correct, and I was completely wrong about this. I thought you were talking about qualifiers: I didn't read what you'd written carefully enough and I responded too quickly. > There is no part of the standard that guarantees that a pointer > conversion from "int*" to "unsigned int*" will not result in an > invalid value. That's right. Andrew.