Oleg Andreev Oleg Andreev - 1 month ago 22
C Question

Writing memcpy conformant with strict aliasing

The general answer when asking "how does one implement memcpy function conformant with strict aliasing rules" is something along the lines of

void *memcpy(void *dest, const void *src, size_t n)
{
for (size_t i = 0; i < n; i++)
((char*)dest)[i] = ((const char*)src)[i];
return dest;
}


However, if I understand correctly, compiler is free to reorder call to memcpy and access to the dest, because it can reorder writes to char* with reads from any other pointer type (strict aliasing rules prevent only reordering of reads from char* with writes to any other pointer type).

Is this correct and if yes, are there any ways to correctly implement memcpy, or should we just rely on builtin memcpy?

Please note, that this question concerns not only memcpy but any deserialization/decoding function.

Answer

The strict aliasing rule specifically excludes casts to char types (see last bullet point below), so the compiler will do the correct thing in your case. Type punning is only a problem when converting things like int to short. Here the compiler may make assumptions that will cause undefined behavior.

C99 §6.5/7:

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,
  • 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.