WG14 member Jens Gustedt says in a blog post on strict aliasing rules:
Character arrays must not be reinterpreted as objects of other types.
Is that, in fact, true? (I guess the corresponding language in the standard is the part saying that if an object has a declared type, then that type is its effective type.) If so, does it mean that an allocator that parcels out memory from a statically declared memory region is unimplementable in standard C?
I know TeX ignores most of Pascal’s type system and treats everything as an array of words because of a similar issue, but I hoped that if I ever found myself in a similar situation in (malloc
-less) C, I could just declare a maximally aligned char
array and keep using structs the usual way. I also fail to see what the point of _Alignas
could possibly be in such a world, except as a standardized device for expressing non-standard requirements (similar to volatile
).
The rules on aliasing are specified in section 6.5p7 of the C standard:
An object shall have its stored value accessed only by an lvalue expression that has one of the following types: 88)
- a type compatible with the effective type of the object,
- a qualified version of a type compatible with the effective type of the object,
- a type that is the signed or unsigned type corresponding to the effective type of the object,
- a type that is the signed or unsigned type corresponding to a qualified version of 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
- a character type.
- The intent of this list is to specify those circumstances in which an object may or may not be aliased
Note that this list allows any object to be accessed via a char *
, but not the reverse, i.e. an object declared as an array of one or more characters can't be accessed as an lvalue of some other type.
This also means that malloc
can't be implemented in a standard compliant way, since there's no way to create memory with no effective type without it. However malloc
is considered part of the implementation and therefore can take of advantage of its knowledge of implementation internals to return a pointer to a block of memory that a compliant program can use.