On Sun, Jan 10, 2010 at 06:24:14PM +0000, Dave Korn wrote: > Eric Botcazou wrote: > >> The aliasing rules treat "char" specially because char is a bit like a > >> "poor main's void". > > > > Not symmetrically though, only for the type of the lvalue expression used > > to > > access the object (C99 6.5.7). > > > > Ok. So if I had four ints, and I wanted to cast the pointers to char and > compare them as 16 chars, that would be OK, because the chars would alias the > ints; but in this case, where they started as chars and I cast them to ints, > those ints don't alias against the original chars. Is that an accurate > precis? > > Andreas, you wrote: "Aliasing is not symmetric". To be precise, we're > saying it's not commutative here; that (A aliases B) does not imply (B aliases > A)? I don't think I've ever heard it expressed that explicitly before.
I think you (and several other people) are actually conflating two separate concepts here. One is aliasing, which can be described as "when can two different lvalues actually refer to the same object". The other is if it is actually allowed to access a particular object through a given lvalue. These two concepts partially overlap, but they are not the same. I would say that aliasing actually is symmetric such that if (A aliases B) then (B aliases A), but that does not necessarily mean that it is safe to access the underlying object through both A and B. (This just depends on how one defines the term "aliasing". Note that aliasing is only defined indirectly in the C standard, and the term itself only occurs in non-normative text.) Take for example the following situation: float f=0; int main(void) { char *cp = (char *)&f; float *fp = &f; *cp = 42; *fp; return 0; } Here the lvalues '*cp' and '*fp' clearly alias each other, in that they both refer to the object 'f'. Section 6.5p7 does not disallow access to 'f' either through '*fp' (which has the same type as the effective type of the object, i.e. 'float') or through '*cp' (whose type is a character type.) (Also note that 6.5p7 is irrelevant when storing a value into '*cp' since that section only talks about accessing the stored value of an object, i.e. reading from it.) However the access to 'f' through the lvalue '*fp' still invokes undefined behaviour since it may at that point contain a trap representation. (If the order of the expressions '*cp = 42' and '*fp' had been switched around, then no undefined behaviour would have occurred.) The standard has special language at several places that essentially says that you can treat any object as an array of unsigned chars both when reading and writing to the object. (You can mostly treat any object as an array of char, or array of signed char as well, but since a signed char can have a trap representation it is not necessarily safe to read from such an lvalue in all situations. Unsigned char is the only type guaranteed to not have any trap representation.) There is no such special language for any other types. If one ignores the special case of character types, the rules basically boil down to: If an object has been declared with some specific type (this includes all objects with automatic or static storage duration) then you can only read from it using an lvalue whose type is compatible with the type as the object. (Possibly with differences in signed/unsigned specification and in qualifiers as described in 6.5p7) If an object does not have a declared type (such as memory allocated through malloc) then if you have stored a value there using an lvalue of some specific type, then you can only read the value using an lvalue of compatible type. (Again possibly with differences in qualifiers and signed/unsigned specifiers.) (Assuming the object is suitably aligned and large enough, there is not really any prohibition against storing a value into an object using an lvalue of a completely different type, but since you cannot read that value back there is not much point in doing so.) Note that most sorts of "type punning" (i.e. treating an object as if it was of a different type than it actually is) is disallowed by the C standard. In particular accessing an array of chars as if it was an array of int is not allowed any more than accessing an array of int as if it was an array of float. -- <Insert your favourite quote here.> Erik Trulsson ertr1...@student.uu.se