Furthermore, char can't be replaced with any other type, because that would violate strict aliasing rules. C11 provides us with a solution: the alignas specifier.

Aliasing and alignment are separate problems. You still have an aliasing issue as your initial object is not untyped like memory obtained from malloc, but has a type of char[size], and while char is free to alias any object, any type cannot necessarily alias char. Normally (i.e. net/disk i/o) this can be dealt with by memcpying into an existing object with the correct type or unionizing the buffer, but opaque types can't participate in a union, and if we had one to copy into we wouldn't be doing this to begin with.

Unfortunately there doesn't appear to be any way to create automatic opaques in standard C, although compilers are pretty conservative with aliasing when character types are involved so you will be hard pressed to encounter bugs with this approach. may_alias attributes can help, but those are of course as standard as alloca.

Pretty sure /u/nooneofnote is correct. The char exception to the aliasing rules is not two-way, it just says you can access any object through an lvalue of type char, not necessarily the reverse. Damn!

The use case is mentioned in the text -- a struct with a flexible array member. Such a struct cannot be instantiated as struct foo f, because the whole point is that you want to allocate extra space after the struct for the last member to grow into, hence the need for the extra size parameter.

That's one use case I mentioned. The example in the code is for a type that is only forward-declared, often called an opaque type. Used in libraries quite a bit to allow the type to be changed without breaking the ABI.